Bring threads into the vvp_vector4_t structure.

This commit is contained in:
steve 2005-08-27 02:34:42 +00:00
parent 4a8be3db9c
commit bc489a7761
4 changed files with 595 additions and 391 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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.
*

View File

@ -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.
*

View File

@ -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.
*