Word oriented bit storage.

This commit is contained in:
steve 2002-05-31 00:05:49 +00:00
parent b5a1d116fa
commit 48f65cef40
1 changed files with 78 additions and 63 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vthread.cc,v 1.74 2002/05/29 16:29:34 steve Exp $"
#ident "$Id: vthread.cc,v 1.75 2002/05/31 00:05:49 steve Exp $"
#endif
# include "vthread.h"
@ -36,6 +36,12 @@
# include <assert.h>
#include <stdio.h>
/* This is the size of an unsigned long in bits. This is just a
convenience macro. */
# define CPU_WORD_BITS (8*sizeof(unsigned long))
# define TOP_BIT (1UL << (CPU_WORD_BITS-1))
/*
* This vhtread_s structure describes all there is to know about a
* thread, including its program counter, all the private bits it
@ -88,7 +94,7 @@ struct vthread_s {
/* This is the program counter. */
unsigned long pc;
/* These hold the private thread bits. */
unsigned char *bits;
unsigned long *bits;
long index[4];
unsigned nbits :16;
/* My parent sets this when it wants me to wake it up. */
@ -106,35 +112,55 @@ struct vthread_s {
struct vthread_s*scope_next, *scope_prev;
};
#if SIZEOF_UNSIGNED_LONG == 8
# define THR_BITS_INIT 0xaaaaaaaaaaaaaaaaUL
#else
# define THR_BITS_INIT 0xaaaaaaaaUL
#endif
static void thr_check_addr(struct vthread_s*thr, unsigned addr)
{
if (addr < thr->nbits)
return;
assert(addr < 0x10000);
while (thr->nbits <= addr) {
thr->bits = (unsigned char*)realloc(thr->bits, thr->nbits/4 + 16);
memset(thr->bits + thr->nbits/4, 0xaa, 16);
thr->nbits += 16*4;
unsigned word_cnt = thr->nbits/(CPU_WORD_BITS/2) + 1;
thr->bits = (unsigned long*)
realloc(thr->bits, word_cnt*sizeof(unsigned long));
thr->bits[word_cnt-1] = THR_BITS_INIT;
thr->nbits = word_cnt * (CPU_WORD_BITS/2);
}
}
static inline unsigned thr_get_bit(struct vthread_s*thr, unsigned addr)
{
assert(addr < thr->nbits);
unsigned idx = addr % 4;
addr /= 4;
return (thr->bits[addr] >> (idx*2)) & 3;
unsigned idx = addr % (CPU_WORD_BITS/2);
addr /= (CPU_WORD_BITS/2);
return (thr->bits[addr] >> (idx*2)) & 3UL;
}
static inline void thr_put_bit(struct vthread_s*thr,
unsigned addr, unsigned val)
{
thr_check_addr(thr, addr);
unsigned idx = addr % 4;
addr /= 4;
unsigned mask = 3 << (idx*2);
if (addr >= thr->nbits)
thr_check_addr(thr, addr);
thr->bits[addr] = (thr->bits[addr] & ~mask) | (val << (idx*2));
unsigned idx = addr % (CPU_WORD_BITS/2);
addr /= (CPU_WORD_BITS/2);
unsigned long mask = 3UL << (idx*2);
unsigned long tmp = val;
thr->bits[addr] = (thr->bits[addr] & ~mask) | (tmp << (idx*2));
}
static inline void thr_clr_bit_(struct vthread_s*thr, unsigned addr)
{
unsigned idx = addr % (CPU_WORD_BITS/2);
addr /= (CPU_WORD_BITS/2);
unsigned long mask = 3UL << (idx*2);
thr->bits[addr] &= ~mask;
}
unsigned vthread_get_bit(struct vthread_s*thr, unsigned addr)
@ -147,13 +173,10 @@ void vthread_put_bit(struct vthread_s*thr, unsigned addr, unsigned bit)
thr_put_bit(thr, addr, bit);
}
# define CPU_BITS (8*sizeof(unsigned long))
# define TOP_BIT (1UL << (CPU_BITS-1))
static unsigned long* vector_to_array(struct vthread_s*thr,
unsigned addr, unsigned wid)
{
unsigned awid = (wid + CPU_BITS - 1) / (8*sizeof(unsigned long));
unsigned awid = (wid + CPU_WORD_BITS - 1) / (CPU_WORD_BITS);
unsigned long*val = new unsigned long[awid];
for (unsigned idx = 0 ; idx < awid ; idx += 1)
@ -165,7 +188,7 @@ static unsigned long* vector_to_array(struct vthread_s*thr,
if (bit & 2)
goto x_out;
val[idx/CPU_BITS] |= bit << (idx % CPU_BITS);
val[idx/CPU_WORD_BITS] |= bit << (idx % CPU_WORD_BITS);
if (addr >= 4)
addr += 1;
}
@ -185,8 +208,8 @@ vthread_t vthread_new(unsigned long pc, struct __vpiScope*scope)
{
vthread_t thr = new struct vthread_s;
thr->pc = pc;
thr->bits = (unsigned char*)malloc(16);
thr->nbits = 16*4;
thr->bits = (unsigned long*)malloc(4 * sizeof(unsigned long));
thr->nbits = 4 * (CPU_WORD_BITS/2);
thr->child = 0;
thr->parent = 0;
thr->wait_next = 0;
@ -349,7 +372,7 @@ bool of_ADD(vthread_t thr, vvp_code_t cp)
unsigned long carry;
carry = 0;
for (unsigned idx = 0 ; (idx*CPU_BITS) < cp->number ; idx += 1) {
for (unsigned idx = 0 ; (idx*CPU_WORD_BITS) < cp->number ; idx += 1) {
unsigned long tmp = lvb[idx] + carry;
unsigned long sum = lva[idx] + tmp;
@ -364,7 +387,7 @@ bool of_ADD(vthread_t thr, vvp_code_t cp)
}
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
unsigned bit = lva[idx/CPU_BITS] >> (idx % CPU_BITS);
unsigned bit = lva[idx/CPU_WORD_BITS] >> (idx % CPU_WORD_BITS);
thr_put_bit(thr, cp->bit_idx[0]+idx, (bit&1) ? 1 : 0);
}
@ -393,7 +416,7 @@ bool of_ADDI(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
unsigned word_count = (cp->number+CPU_BITS-1)/CPU_BITS;
unsigned word_count = (cp->number+CPU_WORD_BITS-1)/CPU_WORD_BITS;
unsigned long*lva = vector_to_array(thr, cp->bit_idx[0], cp->number);
unsigned long*lvb;
@ -408,7 +431,7 @@ bool of_ADDI(vthread_t thr, vvp_code_t cp)
unsigned long carry;
carry = 0;
for (unsigned idx = 0 ; (idx*CPU_BITS) < cp->number ; idx += 1) {
for (unsigned idx = 0 ; (idx*CPU_WORD_BITS) < cp->number ; idx += 1) {
unsigned long tmp = lvb[idx] + carry;
unsigned long sum = lva[idx] + tmp;
@ -423,7 +446,7 @@ bool of_ADDI(vthread_t thr, vvp_code_t cp)
}
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
unsigned bit = lva[idx/CPU_BITS] >> (idx % CPU_BITS);
unsigned bit = lva[idx/CPU_WORD_BITS] >> (idx % CPU_WORD_BITS);
thr_put_bit(thr, cp->bit_idx[0]+idx, (bit&1) ? 1 : 0);
}
@ -1401,6 +1424,20 @@ tally:
return true;
}
static bool of_MOV_clr_(vthread_t thr, vvp_code_t cp)
{
/* Test that the address is OK just once, then use the clear
method that relies on the results of this test. */
unsigned test_addr = cp->bit_idx[0] + cp->number - 1;
if (test_addr >= thr->nbits)
thr_check_addr(thr, test_addr);
for (unsigned idx = 0 ; idx < cp->number ; idx += 1)
thr_clr_bit_(thr, cp->bit_idx[0]+idx);
return true;
}
bool of_MOV(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
@ -1411,6 +1448,13 @@ bool of_MOV(vthread_t thr, vvp_code_t cp)
cp->bit_idx[0]+idx,
thr_get_bit(thr, cp->bit_idx[1]+idx));
} else if (cp->bit_idx[1] == 0) {
/* Detect the special case where this is really just a
large clear. Rewrite the instruction to skip this
test next time around. */
cp->opcode = &of_MOV_clr_;
return cp->opcode(thr, cp);
} else {
for (unsigned idx = 0 ; idx < cp->number ; idx += 1)
thr_put_bit(thr, cp->bit_idx[0]+idx, cp->bit_idx[1]);
@ -1807,11 +1851,11 @@ bool of_SUB(vthread_t thr, vvp_code_t cp)
unsigned long tmp;
unsigned sum = carry;
tmp = lva[idx/CPU_BITS];
sum += 1 & (tmp >> (idx%CPU_BITS));
tmp = lva[idx/CPU_WORD_BITS];
sum += 1 & (tmp >> (idx%CPU_WORD_BITS));
tmp = lvb[idx/CPU_BITS];
sum += 1 & ~(tmp >> (idx%CPU_BITS));
tmp = lvb[idx/CPU_WORD_BITS];
sum += 1 & ~(tmp >> (idx%CPU_WORD_BITS));
carry = sum / 2;
thr_put_bit(thr, cp->bit_idx[0]+idx, (sum&1) ? 1 : 0);
@ -1971,6 +2015,9 @@ bool of_CALL_UFUNC(vthread_t thr, vvp_code_t cp)
/*
* $Log: vthread.cc,v $
* Revision 1.75 2002/05/31 00:05:49 steve
* Word oriented bit storage.
*
* Revision 1.74 2002/05/29 16:29:34 steve
* Add %addi, which is faster to simulate.
*
@ -2070,37 +2117,5 @@ bool of_CALL_UFUNC(vthread_t thr, vvp_code_t cp)
* Revision 1.44 2001/06/18 01:09:32 steve
* More behavioral unary reduction operators.
* (Stephan Boettcher)
*
* Revision 1.43 2001/06/16 23:45:05 steve
* Add support for structural multiply in t-dll.
* Add code generators and vvp support for both
* structural and behavioral multiply.
*
* Revision 1.42 2001/05/30 03:02:35 steve
* Propagate strength-values instead of drive strengths.
*
* Revision 1.41 2001/05/24 04:20:10 steve
* Add behavioral modulus.
*
* Revision 1.40 2001/05/20 00:56:48 steve
* Make vthread_put_but expand the space if needed.
*
* Revision 1.39 2001/05/10 00:26:53 steve
* VVP support for memories in expressions,
* including general support for thread bit
* vectors as system task parameters.
* (Stephan Boettcher)
*
* Revision 1.38 2001/05/08 23:59:33 steve
* Add ivl and vvp.tgt support for memories in
* expressions and l-values. (Stephan Boettcher)
*
* Revision 1.37 2001/05/08 23:32:26 steve
* Add to the debugger the ability to view and
* break on functors.
*
* Add strengths to functors at compile time,
* and Make functors pass their strengths as they
* propagate their output.
*/