Make vvp thread word storage consistently 64 bits.

The vvp thread word storage had previously been changed to always store
64-bit values, but some instructions still only operate on native long
values. This patch ensures all instructions that modify thread words
support 64-bit values.
This commit is contained in:
Martin Whitaker 2009-12-19 18:00:08 +00:00 committed by Stephen Williams
parent f6d1a891a1
commit 13cad6f268
9 changed files with 125 additions and 85 deletions

View File

@ -761,8 +761,9 @@ make vectors of 0, 1, x or z values, so these can be used to
manufacture complex values elsewhere.
The word memory is a region of tagged words. The value in each word
may be native long or real. These words have a distinct address space
from the bits.
may be either a 64-bit unsigned integer (uint64_t), a 64-bit signed
integer (int64_t), or a 64-bit floating point number (double). These
words have a distinct address space from the bits.
* Threads and scopes

View File

@ -99,7 +99,7 @@ extern bool of_INV(vthread_t thr, vvp_code_t code);
extern bool of_IX_ADD(vthread_t thr, vvp_code_t code);
extern bool of_IX_GET(vthread_t thr, vvp_code_t code);
extern bool of_IX_GETV(vthread_t thr, vvp_code_t code);
extern bool of_IX_GETVS(vthread_t thr, vvp_code_t code);
extern bool of_IX_GETV_S(vthread_t thr, vvp_code_t code);
extern bool of_IX_GET_S(vthread_t thr, vvp_code_t code);
extern bool of_IX_LOAD(vthread_t thr, vvp_code_t code);
extern bool of_IX_MUL(vthread_t thr, vvp_code_t code);

View File

@ -144,7 +144,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%ix/get", of_IX_GET, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%ix/get/s",of_IX_GET_S,3,{OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%ix/getv",of_IX_GETV,2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
{ "%ix/getv/s",of_IX_GETVS,2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
{ "%ix/getv/s",of_IX_GETV_S,2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
{ "%ix/load",of_IX_LOAD,3, {OA_NUMBER, OA_BIT1, OA_BIT2} },
{ "%ix/mul", of_IX_MUL, 3, {OA_NUMBER, OA_BIT1, OA_BIT2} },
{ "%ix/sub", of_IX_SUB, 3, {OA_NUMBER, OA_BIT1, OA_BIT2} },

View File

@ -135,13 +135,38 @@ typedef unsigned long vvp_time64_t;
# undef LINUX
#if !defined(HAVE_LROUND)
#if defined(__cplusplus)
extern "C" long lround(double x);
/*
* If the system doesn't provide the lround function, then we provide
* it ourselves here. It is simply the nearest integer, rounded away
* from zero.
*/
inline long int lround(double x)
{
if (x >= 0.0)
return (long)floor(x+0.5);
else
return (long)ceil(x-0.5);
}
/*
* We also need an equivalent function with a 64-bit return value.
*/
inline int64_t i64round(double x)
{
if (x >= 0.0)
return (int64_t)floor(x+0.5);
else
return (int64_t)ceil(x-0.5);
}
#else /* HAVE_LROUND */
#if ((SIZEOF_UNSIGNED_LONG < 8) && (SIZEOF_UNSIGNED_LONG_LONG >= 8))
# define i64round llround
#else
extern long lround(double x);
#endif
# define i64round lround
#endif
#endif /* HAVE_LROUND */
#if !defined(HAVE_NAN)
# define nan(x) (NAN)
#endif

View File

@ -52,22 +52,6 @@ extern "C" int optind;
extern "C" const char*optarg;
#endif
#if !defined(HAVE_LROUND)
/*
* If the system doesn't provide the lround function, then we provide
* it ourselves here. It is simply the nearest integer, rounded away
* from zero.
*/
# include <math.h>
extern "C" long int lround(double x)
{
if (x >= 0.0)
return (long)floor(x+0.5);
else
return (long)ceil(x-0.5);
}
#endif
bool verbose_flag = false;
bool version_flag = false;
static int vvp_return_value = 0;

View File

@ -440,8 +440,8 @@ set bit 4 just like %ix/get.
* %ix/load <idx>, <low>, <high>
This instruction loads an immediate value into the addressed index
register. The index register holds signed 64 bit numeric values, so
<low> and <high> are used to separate the value in two 32 bit chunks.
register. The index register holds 64 bit numeric values, so <low>
and <high> are used to separate the value in two 32 bit chunks.
The idx value selects the index register. This is different from
%ix/get, which loads the index register from a value in the thread bit
vector. The values are unsigned decimal values and are combined as

View File

@ -833,7 +833,7 @@ bool of_ASSIGN_AR(vthread_t thr, vvp_code_t cp)
bool of_ASSIGN_ARD(vthread_t thr, vvp_code_t cp)
{
long adr = thr->words[3].w_int;
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_int;
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_uint;
double value = thr->words[cp->bit_idx[1]].w_real;
if (adr >= 0) {
@ -916,7 +916,7 @@ bool of_ASSIGN_AVD(vthread_t thr, vvp_code_t cp)
unsigned wid = thr->words[0].w_int;
long off = thr->words[1].w_int;
long adr = thr->words[3].w_int;
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_int;
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_uint;
unsigned bit = cp->bit_idx[1];
if (adr < 0) return true;
@ -1014,7 +1014,7 @@ bool of_ASSIGN_V0D(vthread_t thr, vvp_code_t cp)
unsigned wid = thr->words[0].w_int;
assert(wid > 0);
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_int;
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_uint;
unsigned bit = cp->bit_idx[1];
vvp_net_ptr_t ptr (cp->net, 0);
@ -1101,7 +1101,7 @@ bool of_ASSIGN_V0X1D(vthread_t thr, vvp_code_t cp)
{
unsigned wid = thr->words[0].w_int;
long off = thr->words[1].w_int;
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_int;
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_uint;
unsigned bit = cp->bit_idx[1];
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (cp->net->fil);
@ -1207,7 +1207,7 @@ bool of_ASSIGN_WR(vthread_t thr, vvp_code_t cp)
bool of_ASSIGN_WRD(vthread_t thr, vvp_code_t cp)
{
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_int;
vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_uint;
unsigned index = cp->bit_idx[1];
s_vpi_time del;
@ -1777,14 +1777,14 @@ bool of_CMPZ(vthread_t thr, vvp_code_t cp)
bool of_CVT_IR(vthread_t thr, vvp_code_t cp)
{
double r = thr->words[cp->bit_idx[1]].w_real;
thr->words[cp->bit_idx[0]].w_int = lround(r);
thr->words[cp->bit_idx[0]].w_int = i64round(r);
return true;
}
bool of_CVT_RI(vthread_t thr, vvp_code_t cp)
{
long r = thr->words[cp->bit_idx[1]].w_int;
int64_t r = thr->words[cp->bit_idx[1]].w_int;
thr->words[cp->bit_idx[0]].w_real = (double)(r);
return true;
@ -1888,10 +1888,10 @@ bool of_DELAY(vthread_t thr, vvp_code_t cp)
bool of_DELAYX(vthread_t thr, vvp_code_t cp)
{
unsigned long delay;
vvp_time64_t delay;
assert(cp->number < 4);
delay = thr->words[cp->number].w_int;
delay = thr->words[cp->number].w_uint;
schedule_vthread(thr, delay);
return false;
}
@ -2624,39 +2624,15 @@ bool of_IX_LOAD(vthread_t thr, vvp_code_t cp)
* bits of the vector are x or z, then set the value to 0,
* set bit[4] to 1, and give up.
*/
bool of_IX_GET(vthread_t thr, vvp_code_t cp)
static uint64_t vector_to_index(vthread_t thr, unsigned base,
unsigned width, bool signed_flag)
{
unsigned index = cp->bit_idx[0];
unsigned base = cp->bit_idx[1];
unsigned width = cp->number;
unsigned long*array = vector_to_array(thr, base, width);
if (array == 0) {
/* If there are unknowns in the vector bits, then give
up immediately. Set the value to 0, and set thread
bit 4 to 1 to flag the error. */
thr->words[index].w_int = 0;
thr_put_bit(thr, 4, BIT4_1);
return true;
}
thr->words[index].w_int = array[0];
thr_put_bit(thr, 4, BIT4_0);
delete[]array;
return true;
}
bool of_IX_GET_S(vthread_t thr, vvp_code_t cp)
{
unsigned index = cp->bit_idx[0];
unsigned base = cp->bit_idx[1];
unsigned width = cp->number;
uint64_t v = 0;
bool unknown_flag = false;
vvp_bit4_t vv = BIT4_0;
for (unsigned i = 0 ; i<width ; i += 1) {
for (unsigned i = 0 ; i < width ; i += 1) {
vv = thr_get_bit(thr, base);
if (bit4_is_xz(vv)) {
v = 0UL;
@ -2670,19 +2646,37 @@ bool of_IX_GET_S(vthread_t thr, vvp_code_t cp)
base += 1;
}
/* Sign-extend to fill the integer value. */
if (!unknown_flag) {
/* Extend to fill the integer value. */
if (signed_flag && !unknown_flag) {
uint64_t pad = vv;
for (unsigned i = width ; i < 8*sizeof(v) ; i += 1) {
v |= pad << i;
}
}
thr->words[index].w_int = v;
/* Set bit 4 as a flag if the input is unknown. */
thr_put_bit(thr, 4, unknown_flag? BIT4_1 : BIT4_0);
thr_put_bit(thr, 4, unknown_flag ? BIT4_1 : BIT4_0);
return v;
}
bool of_IX_GET(vthread_t thr, vvp_code_t cp)
{
unsigned index = cp->bit_idx[0];
unsigned base = cp->bit_idx[1];
unsigned width = cp->number;
thr->words[index].w_uint = vector_to_index(thr, base, width, false);
return true;
}
bool of_IX_GET_S(vthread_t thr, vvp_code_t cp)
{
unsigned index = cp->bit_idx[0];
unsigned base = cp->bit_idx[1];
unsigned width = cp->number;
thr->words[index].w_int = vector_to_index(thr, base, width, true);
return true;
}
@ -2701,27 +2695,28 @@ bool of_IX_GETV(vthread_t thr, vvp_code_t cp)
vvp_vector4_t vec;
sig->vec4_value(vec);
unsigned long val;
uint64_t val;
bool known_flag = vector4_to_value(vec, val);
if (known_flag)
thr->words[index].w_int = val;
thr->words[index].w_uint = val;
else
thr->words[index].w_int = 0;
thr->words[index].w_uint = 0;
/* Set bit 4 as a flag if the input is unknown. */
thr_put_bit(thr, 4, known_flag? BIT4_0 : BIT4_1);
thr_put_bit(thr, 4, known_flag ? BIT4_0 : BIT4_1);
return true;
}
bool of_IX_GETVS(vthread_t thr, vvp_code_t cp)
bool of_IX_GETV_S(vthread_t thr, vvp_code_t cp)
{
unsigned index = cp->bit_idx[0];
vvp_net_t*net = cp->net;
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*>(net->fil);
if (sig == 0) {
assert(net->fil);
cerr << "%%ix/getv/s error: Net arg not a vector signal? "
<< "fun=" << typeid(*net->fil).name()
<< ", fil=" << (net->fil? typeid(*net->fil).name() : "<>")
@ -2731,7 +2726,7 @@ bool of_IX_GETVS(vthread_t thr, vvp_code_t cp)
vvp_vector4_t vec;
sig->vec4_value(vec);
long val;
int64_t val;
bool known_flag = vector4_to_value(vec, val, true, true);
if (known_flag)
@ -2740,7 +2735,7 @@ bool of_IX_GETVS(vthread_t thr, vvp_code_t cp)
thr->words[index].w_int = 0;
/* Set bit 4 as a flag if the input is unknown. */
thr_put_bit(thr, 4, known_flag? BIT4_0 : BIT4_1);
thr_put_bit(thr, 4, known_flag ? BIT4_0 : BIT4_1);
return true;
}
@ -2922,6 +2917,11 @@ bool of_LOAD_AV(vthread_t thr, vvp_code_t cp)
/*
* %load/vp0, %load/vp0/s, %load/avp0 and %load/avp0/s share this function.
*/
#if (SIZEOF_UNSIGNED_LONG >= 8)
# define CPU_WORD_STRIDE CPU_WORD_BITS - 1 // avoid a warning
#else
# define CPU_WORD_STRIDE CPU_WORD_BITS
#endif
static void load_vp0_common(vthread_t thr, vvp_code_t cp, const vvp_vector4_t&sig_value)
{
unsigned bit = cp->bit_idx[0];
@ -2941,16 +2941,10 @@ static void load_vp0_common(vthread_t thr, vvp_code_t cp, const vvp_vector4_t&si
unsigned words = (wid + CPU_WORD_BITS - 1) / CPU_WORD_BITS;
unsigned long carry = 0;
unsigned long imm = addend;
if (addend >= 0) {
for (unsigned idx = 0 ; idx < words ; idx += 1) {
val[idx] = add_with_carry(val[idx], imm, carry);
imm = 0UL;
}
} else {
for (unsigned idx = 0 ; idx < words ; idx += 1) {
val[idx] = add_with_carry(val[idx], imm, carry);
imm = -1UL;
}
for (unsigned idx = 0 ; idx < words ; idx += 1) {
val[idx] = add_with_carry(val[idx], imm, carry);
addend >>= CPU_WORD_STRIDE;
imm = addend;
}
/* Copy the vector bits into the bits4 vector. Do the copy

View File

@ -1510,6 +1510,41 @@ bool vector4_to_value(const vvp_vector4_t&vec, unsigned long&val)
}
#ifndef UL_AND_TIME64_SAME
bool vector4_to_value(const vvp_vector4_t&vec, int64_t&val,
bool is_signed, bool is_arithmetic)
{
long res = 0;
long msk = 1;
bool rc_flag = true;
unsigned size = vec.size();
if (size > 8*sizeof(val)) size = 8*sizeof(val);
for (unsigned idx = 0 ; idx < size ; idx += 1) {
switch (vec.value(idx)) {
case BIT4_0:
break;
case BIT4_1:
res |= msk;
break;
default:
if (is_arithmetic)
return false;
else
rc_flag = false;
}
msk <<= 1L;
}
if (is_signed && vec.value(vec.size()-1) == BIT4_1) {
if (vec.size() < 8*sizeof(val))
res |= (-1L) << vec.size();
}
val = res;
return rc_flag;
}
bool vector4_to_value(const vvp_vector4_t&vec, vvp_time64_t&val)
{
vvp_time64_t res = 0;

View File

@ -475,6 +475,7 @@ template <class T> extern T coerce_to_width(const T&that, unsigned width);
extern bool vector4_to_value(const vvp_vector4_t&a, long&val, bool is_signed, bool is_arithmetic =true);
extern bool vector4_to_value(const vvp_vector4_t&a, unsigned long&val);
#ifndef UL_AND_TIME64_SAME
extern bool vector4_to_value(const vvp_vector4_t&a, int64_t&val, bool is_signed, bool is_arithmetic =true);
extern bool vector4_to_value(const vvp_vector4_t&a, vvp_time64_t&val);
#endif
extern bool vector4_to_value(const vvp_vector4_t&a, double&val, bool is_signed);