Bring threads into the vvp_vector4_t structure.
This commit is contained in:
parent
4a8be3db9c
commit
bc489a7761
642
vvp/vthread.cc
642
vvp/vthread.cc
File diff suppressed because it is too large
Load Diff
|
|
@ -19,9 +19,11 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vthread.h,v 1.11 2003/07/03 20:03:36 steve Exp $"
|
||||
#ident "$Id: vthread.h,v 1.12 2005/08/27 02:34:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_net.h"
|
||||
|
||||
/*
|
||||
* A vthread is a simulation thread that executes instructions when
|
||||
* they are scheduled. This structure contains all the thread specific
|
||||
|
|
@ -69,14 +71,17 @@ extern void vthread_schedule_list(vthread_t thr);
|
|||
* example, when a VPI implementation function needs to access the bit
|
||||
* space of the thread.
|
||||
*/
|
||||
extern unsigned vthread_get_bit(struct vthread_s*thr, unsigned addr);
|
||||
extern void vthread_put_bit(struct vthread_s*thr, unsigned addr, unsigned bit);
|
||||
extern vvp_bit4_t vthread_get_bit(struct vthread_s*thr, unsigned addr);
|
||||
extern void vthread_put_bit(struct vthread_s*thr, unsigned addr, vvp_bit4_t bit);
|
||||
|
||||
extern double vthread_get_real(struct vthread_s*thr, unsigned addr);
|
||||
extern void vthread_put_real(struct vthread_s*thr, unsigned addr, double val);
|
||||
|
||||
/*
|
||||
* $Log: vthread.h,v $
|
||||
* Revision 1.12 2005/08/27 02:34:43 steve
|
||||
* Bring threads into the vvp_vector4_t structure.
|
||||
*
|
||||
* Revision 1.11 2003/07/03 20:03:36 steve
|
||||
* Remove the vvp_cpoint_t indirect code pointer.
|
||||
*
|
||||
|
|
|
|||
272
vvp/vvp_net.cc
272
vvp/vvp_net.cc
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: vvp_net.cc,v 1.41 2005/07/06 04:29:25 steve Exp $"
|
||||
#ident "$Id: vvp_net.cc,v 1.42 2005/08/27 02:34:43 steve Exp $"
|
||||
|
||||
# include "config.h"
|
||||
# include "vvp_net.h"
|
||||
|
|
@ -56,15 +56,6 @@ vvp_bit4_t add_with_carry(vvp_bit4_t a, vvp_bit4_t b, vvp_bit4_t&c)
|
|||
}
|
||||
}
|
||||
|
||||
bool bit4_is_xz(vvp_bit4_t a)
|
||||
{
|
||||
if (a == BIT4_X)
|
||||
return true;
|
||||
if (a == BIT4_Z)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
vvp_bit4_t operator & (vvp_bit4_t a, vvp_bit4_t b)
|
||||
{
|
||||
if (a == BIT4_0)
|
||||
|
|
@ -189,20 +180,270 @@ void vvp_vector4_t::copy_from_(const vvp_vector4_t&that)
|
|||
}
|
||||
}
|
||||
|
||||
vvp_vector4_t::vvp_vector4_t(unsigned size)
|
||||
: size_(size)
|
||||
void vvp_vector4_t::allocate_words_(unsigned wid, unsigned long init)
|
||||
{
|
||||
if (size_ > BITS_PER_WORD) {
|
||||
unsigned cnt = (size_ + BITS_PER_WORD - 1) / BITS_PER_WORD;
|
||||
bits_ptr_ = new unsigned long[cnt];
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
bits_ptr_[idx] = WORD_X_BITS;
|
||||
bits_ptr_[idx] = init;
|
||||
|
||||
} else {
|
||||
bits_val_ = WORD_X_BITS;
|
||||
bits_val_ = init;
|
||||
}
|
||||
}
|
||||
|
||||
vvp_vector4_t::vvp_vector4_t(const vvp_vector4_t&that,
|
||||
unsigned adr, unsigned wid)
|
||||
{
|
||||
size_ = wid;
|
||||
assert((adr + wid) <= that.size_);
|
||||
|
||||
allocate_words_(wid, WORD_X_BITS);
|
||||
|
||||
if (wid > BITS_PER_WORD) {
|
||||
/* In this case, the subvector and the source vector are
|
||||
long. Do the transfer reasonably efficiently. */
|
||||
unsigned ptr = adr / BITS_PER_WORD;
|
||||
unsigned off = adr % BITS_PER_WORD;
|
||||
unsigned noff = BITS_PER_WORD - off;
|
||||
unsigned long lmask = (1 << 2*off) - 1;
|
||||
unsigned trans = 0;
|
||||
unsigned dst = 0;
|
||||
while (trans < wid) {
|
||||
// The low bits of the result.
|
||||
bits_ptr_[dst] = (that.bits_ptr_[ptr] & ~lmask) >> 2*off;
|
||||
trans += noff;
|
||||
|
||||
if (trans >= wid)
|
||||
break;
|
||||
|
||||
ptr += 1;
|
||||
bits_ptr_[dst] |= (that.bits_ptr_[ptr] & lmask) << 2*noff;
|
||||
trans += off;
|
||||
dst += 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
set_bit(idx, that.value(adr+idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the size of the vvp_vector4_t vector to the new size. Copy
|
||||
* the old values, as many as well fit, into the new vector.
|
||||
*/
|
||||
void vvp_vector4_t::resize(unsigned newsize)
|
||||
{
|
||||
if (size_ == newsize)
|
||||
return;
|
||||
|
||||
unsigned cnt = (size_ + BITS_PER_WORD - 1) / BITS_PER_WORD;
|
||||
|
||||
if (newsize > BITS_PER_WORD) {
|
||||
unsigned newcnt = (newsize + BITS_PER_WORD - 1) / BITS_PER_WORD;
|
||||
unsigned long*newbits = new unsigned long[newcnt];
|
||||
|
||||
if (cnt > 1) {
|
||||
unsigned trans = cnt;
|
||||
if (trans > newcnt)
|
||||
trans = newcnt;
|
||||
|
||||
for (unsigned idx = 0 ; idx < trans ; idx += 1)
|
||||
newbits[idx] = bits_ptr_[idx];
|
||||
|
||||
delete[]bits_ptr_;
|
||||
|
||||
} else {
|
||||
newbits[0] = bits_val_;
|
||||
}
|
||||
|
||||
for (unsigned idx = cnt ; idx < newcnt ; idx += 1)
|
||||
newbits[idx] = WORD_X_BITS;
|
||||
|
||||
size_ = newsize;
|
||||
bits_ptr_ = newbits;
|
||||
|
||||
} else {
|
||||
unsigned long newval;
|
||||
if (cnt > 1) {
|
||||
newval = bits_ptr_[0];
|
||||
delete[]bits_ptr_;
|
||||
bits_val_ = newval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned long* vvp_vector4_t::subarray(unsigned adr, unsigned wid) const
|
||||
{
|
||||
const unsigned BIT2_PER_WORD = 8*sizeof(unsigned long);
|
||||
unsigned awid = (wid + BIT2_PER_WORD - 1) / (BIT2_PER_WORD);
|
||||
unsigned long*val = new unsigned long[awid];
|
||||
|
||||
for (unsigned idx = 0 ; idx < awid ; idx += 1)
|
||||
val[idx] = 0;
|
||||
|
||||
if (size_ <= BITS_PER_WORD) {
|
||||
/* Handle the special case that the array is small. The
|
||||
entire value of the vector4 is within the bits_val_
|
||||
so we know that the result is a single word, the
|
||||
source is a single word, and we just have to loop
|
||||
through that word. */
|
||||
unsigned long tmp = bits_val_ >> 2UL*adr;
|
||||
tmp &= (1UL << 2*wid) - 1;
|
||||
if (tmp & WORD_X_BITS)
|
||||
goto x_out;
|
||||
|
||||
unsigned long mask1 = 1;
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
if (tmp & 1) val[0] |= mask1;
|
||||
mask1 <<= 1UL;
|
||||
tmp >>= 2UL;
|
||||
}
|
||||
return val;
|
||||
|
||||
} else {
|
||||
|
||||
/* Get the first word we are scanning. We may in fact be
|
||||
somewhere in the middle of that word. */
|
||||
unsigned long tmp = bits_ptr_[adr/BITS_PER_WORD];
|
||||
tmp >>= 2UL * (adr%BITS_PER_WORD);
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
/* Starting a new word? */
|
||||
if (adr%BITS_PER_WORD == 0)
|
||||
tmp = bits_ptr_[adr/BITS_PER_WORD];
|
||||
|
||||
if (tmp&2)
|
||||
goto x_out;
|
||||
if (tmp&1)
|
||||
val[idx/BIT2_PER_WORD] |= 1UL << (idx % BIT2_PER_WORD);
|
||||
|
||||
adr += 1;
|
||||
tmp >>= 2UL;
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
|
||||
x_out:
|
||||
delete[]val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vvp_vector4_t::set_vec(unsigned adr, const vvp_vector4_t&that)
|
||||
{
|
||||
assert(adr+that.size_ <= size_);
|
||||
|
||||
if (size_ <= BITS_PER_WORD) {
|
||||
|
||||
/* The destination vector (me!) is within a bits_val_
|
||||
word, so the subvector is certainly within a
|
||||
bits_val_ word. Therefore, the entire operation is a
|
||||
matter of writing the bits of that into the addressed
|
||||
bits of this. The mask below is calculated to be 1
|
||||
for all the bits that are to come from that. Do the
|
||||
job by some shifting, masking and OR. */
|
||||
|
||||
unsigned long lmask = (1UL << 2UL*adr) - 1;
|
||||
unsigned long hmask = (1 << 2UL*(adr+that.size_)) - 1;
|
||||
unsigned long mask = hmask & ~lmask;
|
||||
|
||||
bits_val_ =
|
||||
(bits_val_ & ~mask)
|
||||
| ((that.bits_val_<<2UL*adr) & mask);
|
||||
|
||||
} else if (that.size_ <= BITS_PER_WORD) {
|
||||
|
||||
unsigned long dptr = adr / BITS_PER_WORD;
|
||||
unsigned long doff = adr % BITS_PER_WORD;
|
||||
|
||||
unsigned long lmask = (1UL<<2UL*doff) - 1;
|
||||
unsigned long hmask = (1UL << 2UL*(doff+that.size_)) - 1;
|
||||
unsigned long mask = hmask & ~lmask;
|
||||
|
||||
bits_ptr_[dptr] =
|
||||
(bits_ptr_[dptr] & ~mask)
|
||||
| ((that.bits_val_ << 2UL*doff) & mask);
|
||||
|
||||
if (doff + that.size_ > BITS_PER_WORD) {
|
||||
unsigned tail = doff + that.size_ - BITS_PER_WORD;
|
||||
mask = (1UL << 2UL*tail) - 1;
|
||||
|
||||
dptr += 1;
|
||||
bits_ptr_[dptr] =
|
||||
(bits_ptr_[dptr] & ~mask)
|
||||
| ((that.bits_val_ >> 2UL*(that.size_-tail)) & mask);
|
||||
}
|
||||
|
||||
} else if (adr%BITS_PER_WORD == 0) {
|
||||
|
||||
/* In this case, both vectors are long, but the
|
||||
destination is neatly aligned. That means all but the
|
||||
last word can be simply copied with no masking. */
|
||||
|
||||
unsigned remain = that.size_;
|
||||
unsigned sptr = 0;
|
||||
unsigned dptr = adr / BITS_PER_WORD;
|
||||
while (remain >= BITS_PER_WORD) {
|
||||
bits_ptr_[dptr++] = that.bits_ptr_[sptr++];
|
||||
remain -= BITS_PER_WORD;
|
||||
}
|
||||
|
||||
if (remain > 0) {
|
||||
unsigned long mask = (1UL << 2UL*remain) - 1;
|
||||
bits_ptr_[dptr] =
|
||||
(bits_ptr_[dptr] & ~mask)
|
||||
| (that.bits_ptr_[sptr] & mask);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* We know that there are two long vectors, and we know
|
||||
that the destination is definitely NOT aligned. */
|
||||
unsigned remain = that.size_;
|
||||
unsigned sptr = 0;
|
||||
unsigned dptr = adr / BITS_PER_WORD;
|
||||
unsigned doff = adr % BITS_PER_WORD;
|
||||
unsigned long lmask = (1UL << 2UL*doff) - 1;
|
||||
unsigned ndoff = BITS_PER_WORD - doff;
|
||||
while (remain >= BITS_PER_WORD) {
|
||||
bits_ptr_[dptr] =
|
||||
(bits_ptr_[dptr] & lmask)
|
||||
| ((that.bits_ptr_[sptr] << 2UL*doff) & ~lmask);
|
||||
dptr += 1;
|
||||
|
||||
bits_ptr_[dptr] =
|
||||
(bits_ptr_[dptr] & ~lmask)
|
||||
| ((that.bits_ptr_[sptr] >> 2UL*ndoff) & lmask);
|
||||
|
||||
remain -= BITS_PER_WORD;
|
||||
sptr += 1;
|
||||
}
|
||||
|
||||
unsigned long hmask = (1UL << 2UL*(doff+remain)) - 1;
|
||||
unsigned long mask = hmask & ~lmask;
|
||||
|
||||
bits_ptr_[dptr] =
|
||||
(bits_ptr_[dptr] & ~mask)
|
||||
| ((that.bits_ptr_[sptr] << 2UL*doff) & mask);
|
||||
|
||||
if (doff + remain > BITS_PER_WORD) {
|
||||
unsigned tail = doff + remain - BITS_PER_WORD;
|
||||
mask = (1UL << 2UL*tail) - 1;
|
||||
|
||||
dptr += 1;
|
||||
bits_ptr_[dptr] =
|
||||
(bits_ptr_[dptr] & ~mask)
|
||||
| ((that.bits_ptr_[sptr] >> 2UL*(remain-tail))&mask);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool vvp_vector4_t::eeq(const vvp_vector4_t&that) const
|
||||
{
|
||||
|
|
@ -1390,6 +1631,9 @@ vvp_bit4_t compare_gtge_signed(const vvp_vector4_t&a,
|
|||
|
||||
/*
|
||||
* $Log: vvp_net.cc,v $
|
||||
* Revision 1.42 2005/08/27 02:34:43 steve
|
||||
* Bring threads into the vvp_vector4_t structure.
|
||||
*
|
||||
* Revision 1.41 2005/07/06 04:29:25 steve
|
||||
* Implement real valued signals and arith nodes.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: vvp_net.h,v 1.43 2005/07/14 23:34:19 steve Exp $"
|
||||
#ident "$Id: vvp_net.h,v 1.44 2005/08/27 02:34:43 steve Exp $"
|
||||
|
||||
# include "config.h"
|
||||
# include <stddef.h>
|
||||
|
|
@ -63,8 +63,11 @@ enum vvp_bit4_t {
|
|||
};
|
||||
|
||||
extern vvp_bit4_t add_with_carry(vvp_bit4_t a, vvp_bit4_t b, vvp_bit4_t&c);
|
||||
/* Return TRUE if the bit is BIT4_X or BIT4_Z */
|
||||
extern bool bit4_is_xz(vvp_bit4_t a);
|
||||
|
||||
/* Return TRUE if the bit is BIT4_X or BIT4_Z. The fast
|
||||
implementation here relies on the encoding of vvp_bit4_t values. */
|
||||
inline bool bit4_is_xz(vvp_bit4_t a) { return a >= 2; }
|
||||
|
||||
/* Some common boolean operators. These implement the Verilog rules
|
||||
for 4-value bit operations. */
|
||||
extern vvp_bit4_t operator ~ (vvp_bit4_t a);
|
||||
|
|
@ -85,7 +88,11 @@ extern ostream& operator<< (ostream&o, vvp_bit4_t a);
|
|||
class vvp_vector4_t {
|
||||
|
||||
public:
|
||||
explicit vvp_vector4_t(unsigned size =0);
|
||||
explicit vvp_vector4_t(unsigned size =0, vvp_bit4_t bits =BIT4_X);
|
||||
|
||||
// Construct a vector4 from the subvalue of another vector4.
|
||||
explicit vvp_vector4_t(const vvp_vector4_t&that,
|
||||
unsigned adr, unsigned wid);
|
||||
|
||||
vvp_vector4_t(const vvp_vector4_t&that);
|
||||
vvp_vector4_t& operator= (const vvp_vector4_t&that);
|
||||
|
|
@ -93,8 +100,19 @@ class vvp_vector4_t {
|
|||
~vvp_vector4_t();
|
||||
|
||||
unsigned size() const { return size_; }
|
||||
void resize(unsigned new_size);
|
||||
|
||||
// Get the bit at the specified address
|
||||
vvp_bit4_t value(unsigned idx) const;
|
||||
// Get the vector4 subvector starting at the address
|
||||
vvp_vector4_t subvalue(unsigned idx, unsigned size) const;
|
||||
// Get the 2-value bits for the subvector. This returns a new
|
||||
// array of longs, or a nil pointer if an XZ bit was detected
|
||||
// in the array.
|
||||
unsigned long*subarray(unsigned idx, unsigned size) const;
|
||||
|
||||
void set_bit(unsigned idx, vvp_bit4_t val);
|
||||
void set_vec(unsigned idx, const vvp_vector4_t&that);
|
||||
|
||||
// Test that the vectors are exactly equal
|
||||
bool eeq(const vvp_vector4_t&that) const;
|
||||
|
|
@ -109,9 +127,15 @@ class vvp_vector4_t {
|
|||
// Number of vvp_bit4_t bits that can be shoved into a word.
|
||||
enum { BITS_PER_WORD = 8*sizeof(unsigned long)/2 };
|
||||
#if SIZEOF_UNSIGNED_LONG == 8
|
||||
enum { WORD_0_BITS = 0x0000000000000000UL };
|
||||
enum { WORD_1_BITS = 0x5555555555555555UL };
|
||||
enum { WORD_X_BITS = 0xaaaaaaaaaaaaaaaaUL };
|
||||
enum { WORD_Z_BITS = 0xffffffffffffffffUL };
|
||||
#elif SIZEOF_UNSIGNED_LONG == 4
|
||||
enum { WORD_0_BITS = 0x00000000UL };
|
||||
enum { WORD_1_BITS = 0x55555555UL };
|
||||
enum { WORD_X_BITS = 0xaaaaaaaaUL };
|
||||
enum { WORD_Z_BITS = 0xffffffffUL };
|
||||
#else
|
||||
#error "WORD_X_BITS not defined for this architecture?"
|
||||
#endif
|
||||
|
|
@ -120,6 +144,8 @@ class vvp_vector4_t {
|
|||
// the data from that object into this object.
|
||||
void copy_from_(const vvp_vector4_t&that);
|
||||
|
||||
void allocate_words_(unsigned size, unsigned long init);
|
||||
|
||||
unsigned size_;
|
||||
union {
|
||||
unsigned long bits_val_;
|
||||
|
|
@ -132,6 +158,19 @@ inline vvp_vector4_t::vvp_vector4_t(const vvp_vector4_t&that)
|
|||
copy_from_(that);
|
||||
}
|
||||
|
||||
inline vvp_vector4_t::vvp_vector4_t(unsigned size, vvp_bit4_t val)
|
||||
: size_(size)
|
||||
{
|
||||
/* note: this relies on the bit encoding for the vvp_bit4_t. */
|
||||
const static unsigned long init_table[4] = {
|
||||
WORD_0_BITS,
|
||||
WORD_1_BITS,
|
||||
WORD_X_BITS,
|
||||
WORD_Z_BITS };
|
||||
|
||||
allocate_words_(size, init_table[val]);
|
||||
}
|
||||
|
||||
inline vvp_vector4_t::~vvp_vector4_t()
|
||||
{
|
||||
if (size_ > BITS_PER_WORD) {
|
||||
|
|
@ -175,6 +214,11 @@ inline vvp_bit4_t vvp_vector4_t::value(unsigned idx) const
|
|||
return (vvp_bit4_t) (bits & 3);
|
||||
}
|
||||
|
||||
inline vvp_vector4_t vvp_vector4_t::subvalue(unsigned adr, unsigned wid) const
|
||||
{
|
||||
return vvp_vector4_t(*this, adr, wid);
|
||||
}
|
||||
|
||||
inline void vvp_vector4_t::set_bit(unsigned idx, vvp_bit4_t val)
|
||||
{
|
||||
assert(idx < size_);
|
||||
|
|
@ -955,6 +999,9 @@ inline void vvp_send_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&val,
|
|||
|
||||
/*
|
||||
* $Log: vvp_net.h,v $
|
||||
* Revision 1.44 2005/08/27 02:34:43 steve
|
||||
* Bring threads into the vvp_vector4_t structure.
|
||||
*
|
||||
* Revision 1.43 2005/07/14 23:34:19 steve
|
||||
* gcc4 compile errors.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue