Fix for pr2913404.

In combination with the patch to make all operations on thread words
operate on 64-bit values, this patch ensures casts between real values
and large vector values work correctly.
This commit is contained in:
Martin Whitaker 2009-12-19 23:34:54 +00:00 committed by Stephen Williams
parent 13cad6f268
commit b416176c4d
7 changed files with 119 additions and 98 deletions

View File

@ -266,7 +266,7 @@ void draw_eval_expr_into_integer(ivl_expr_t expr, unsigned ix)
case IVL_VT_REAL: case IVL_VT_REAL:
word = draw_eval_real(expr); word = draw_eval_real(expr);
clr_word(word); clr_word(word);
fprintf(vvp_out, " %%cvt/ir %u, %u;\n", ix, word); fprintf(vvp_out, " %%cvt/sr %u, %u;\n", ix, word);
break; break;
default: default:

View File

@ -274,11 +274,37 @@ static int draw_realnum_real(ivl_expr_t expr)
return res; return res;
} }
/*
* The real value of a logic expression is the integer value of the
* expression converted to real.
*/
static int draw_real_logic_expr(ivl_expr_t expr, int stuff_ok_flag)
{
int res = allocate_word();
struct vector_info sv = draw_eval_expr(expr, stuff_ok_flag);
const char*sign_flag = ivl_expr_signed(expr)? "/s" : "";
if (sv.wid > 64) {
fprintf(vvp_out, " %%cvt/rv%s %d, %u, %u;\n",
sign_flag, res, sv.base, sv.wid);
} else {
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n",
sign_flag, res, sv.base, sv.wid);
if (ivl_expr_signed(expr))
fprintf(vvp_out, " %%cvt/rs %d, %d;\n", res, res);
else
fprintf(vvp_out, " %%cvt/ru %d, %d;\n", res, res);
}
clr_vector(sv);
return res;
}
static int draw_sfunc_real(ivl_expr_t expr) static int draw_sfunc_real(ivl_expr_t expr)
{ {
struct vector_info sv;
int res; int res;
const char*sign_flag = "";
switch (ivl_expr_value(expr)) { switch (ivl_expr_value(expr)) {
@ -298,17 +324,7 @@ static int draw_sfunc_real(ivl_expr_t expr)
/* If the value of the sfunc is a vector, then evaluate /* If the value of the sfunc is a vector, then evaluate
it as a vector, then convert the result to a real it as a vector, then convert the result to a real
(via an index register) for the result. */ (via an index register) for the result. */
sv = draw_eval_expr(expr, 0); res = draw_real_logic_expr(expr, 0);
clr_vector(sv);
if (ivl_expr_signed(expr))
sign_flag = "/s";
res = allocate_word();
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n",
sign_flag, res, sv.base, sv.wid);
fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res);
break; break;
default: default:
@ -319,25 +335,6 @@ static int draw_sfunc_real(ivl_expr_t expr)
return res; return res;
} }
/*
* The real value of a signal is the integer value of a signal
* converted to real.
*/
static int draw_signal_real_logic(ivl_expr_t expr)
{
int res = allocate_word();
struct vector_info sv = draw_eval_expr(expr, 0);
const char*sign_flag = ivl_expr_signed(expr)? "/s" : "";
fprintf(vvp_out, " %%ix/get%s %d, %u, %u; logic signal as real\n",
sign_flag, res, sv.base, sv.wid);
clr_vector(sv);
fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res);
return res;
}
static int draw_signal_real_real(ivl_expr_t expr) static int draw_signal_real_real(ivl_expr_t expr)
{ {
ivl_signal_t sig = ivl_expr_signal(expr); ivl_signal_t sig = ivl_expr_signal(expr);
@ -361,7 +358,7 @@ static int draw_signal_real(ivl_expr_t expr)
ivl_signal_t sig = ivl_expr_signal(expr); ivl_signal_t sig = ivl_expr_signal(expr);
switch (ivl_signal_data_type(sig)) { switch (ivl_signal_data_type(sig)) {
case IVL_VT_LOGIC: case IVL_VT_LOGIC:
return draw_signal_real_logic(expr); return draw_real_logic_expr(expr, 0);
case IVL_VT_REAL: case IVL_VT_REAL:
return draw_signal_real_real(expr); return draw_signal_real_real(expr);
default: default:
@ -439,41 +436,11 @@ static int draw_unary_real(ivl_expr_t expr)
ivl_expr_t sube; ivl_expr_t sube;
int sub; int sub;
/* If the opcode is a ~ then the sub expression must not be a /* If the opcode is a ~ or a ! then the sub expression must not be
* real expression, so use vector evaluation and then convert * a real expression, so use vector evaluation and then convert
* that result to a real value. */ * that result to a real value. */
if (ivl_expr_opcode(expr) == '~') { if ((ivl_expr_opcode(expr) == '~') || (ivl_expr_opcode(expr) == '!')) {
struct vector_info vi; return draw_real_logic_expr(expr, STUFF_OK_XZ);
int res;
const char*sign_flag;
vi = draw_eval_expr(expr, STUFF_OK_XZ);
res = allocate_word();
sign_flag = ivl_expr_signed(expr)? "/s" : "";
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n",
sign_flag, res, vi.base, vi.wid);
fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res);
clr_vector(vi);
return res;
}
if (ivl_expr_opcode(expr) == '!') {
struct vector_info vi;
int res;
const char*sign_flag;
vi = draw_eval_expr(expr, STUFF_OK_XZ);
res = allocate_word();
sign_flag = ivl_expr_signed(expr)? "/s" : "";
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n",
sign_flag, res, vi.base, vi.wid);
fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res);
clr_vector(vi);
return res;
} }
sube = ivl_expr_oper1(expr); sube = ivl_expr_oper1(expr);
@ -512,20 +479,7 @@ int draw_eval_real(ivl_expr_t expr)
* result to a real value. This is required to get integer * result to a real value. This is required to get integer
* division to work correctly. */ * division to work correctly. */
if (ivl_expr_value(expr) != IVL_VT_REAL) { if (ivl_expr_value(expr) != IVL_VT_REAL) {
struct vector_info vi; return draw_real_logic_expr(expr, STUFF_OK_XZ);
int res;
const char*sign_flag;
vi = draw_eval_expr(expr, STUFF_OK_XZ);
res = allocate_word();
sign_flag = ivl_expr_signed(expr)? "/s" : "";
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n", sign_flag, res,
vi.base, vi.wid);
fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res);
clr_vector(vi);
return res;
} }
switch (ivl_expr_type(expr)) { switch (ivl_expr_type(expr)) {
@ -573,7 +527,7 @@ int draw_eval_real(ivl_expr_t expr)
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n", fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n",
sign_flag, res, sv.base, sv.wid); sign_flag, res, sv.base, sv.wid);
fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res); fprintf(vvp_out, " %%cvt/rs %d, %d;\n", res, res);
} else { } else {
fprintf(stderr, "XXXX Evaluate real expression (%d)\n", fprintf(stderr, "XXXX Evaluate real expression (%d)\n",

View File

@ -1455,7 +1455,7 @@ static int show_stmt_delayx(ivl_statement_t net, ivl_scope_t sscope)
case IVL_VT_REAL: { case IVL_VT_REAL: {
int word = draw_eval_real(exp); int word = draw_eval_real(exp);
fprintf(vvp_out, " %%cvt/ir 0, %d;\n", word); fprintf(vvp_out, " %%cvt/ur 0, %d;\n", word);
clr_word(word); clr_word(word);
break; break;
} }

View File

@ -73,8 +73,12 @@ extern bool of_CMPWS(vthread_t thr, vvp_code_t code);
extern bool of_CMPWU(vthread_t thr, vvp_code_t code); extern bool of_CMPWU(vthread_t thr, vvp_code_t code);
extern bool of_CMPX(vthread_t thr, vvp_code_t code); extern bool of_CMPX(vthread_t thr, vvp_code_t code);
extern bool of_CMPZ(vthread_t thr, vvp_code_t code); extern bool of_CMPZ(vthread_t thr, vvp_code_t code);
extern bool of_CVT_IR(vthread_t thr, vvp_code_t code); extern bool of_CVT_RS(vthread_t thr, vvp_code_t code);
extern bool of_CVT_RI(vthread_t thr, vvp_code_t code); extern bool of_CVT_RU(vthread_t thr, vvp_code_t code);
extern bool of_CVT_RV(vthread_t thr, vvp_code_t code);
extern bool of_CVT_RV_S(vthread_t thr, vvp_code_t code);
extern bool of_CVT_SR(vthread_t thr, vvp_code_t code);
extern bool of_CVT_UR(vthread_t thr, vvp_code_t code);
extern bool of_CVT_VR(vthread_t thr, vvp_code_t code); extern bool of_CVT_VR(vthread_t thr, vvp_code_t code);
extern bool of_DEASSIGN(vthread_t thr, vvp_code_t code); extern bool of_DEASSIGN(vthread_t thr, vvp_code_t code);
extern bool of_DEASSIGN_WR(vthread_t thr, vvp_code_t code); extern bool of_DEASSIGN_WR(vthread_t thr, vvp_code_t code);

View File

@ -119,8 +119,12 @@ const static struct opcode_table_s opcode_table[] = {
{ "%cmp/z", of_CMPZ, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%cmp/z", of_CMPZ, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmpi/s", of_CMPIS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%cmpi/s", of_CMPIS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmpi/u", of_CMPIU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%cmpi/u", of_CMPIU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cvt/ir", of_CVT_IR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%cvt/rs", of_CVT_RS, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cvt/ri", of_CVT_RI, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%cvt/ru", of_CVT_RU, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cvt/rv", of_CVT_RV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cvt/rv/s", of_CVT_RV_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cvt/sr", of_CVT_SR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cvt/ur", of_CVT_UR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cvt/vr", of_CVT_VR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%cvt/vr", of_CVT_VR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%deassign",of_DEASSIGN,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%deassign",of_DEASSIGN,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%deassign/wr",of_DEASSIGN_WR,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%deassign/wr",of_DEASSIGN_WR,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },

View File

@ -275,13 +275,33 @@ instruction will also treat x values in either operand as don't care.
Only bit 4 is set by these instructions. Only bit 4 is set by these instructions.
* %cvt/ir <bit-l>, <bit-r> * %cvt/sr <bit-l>, <bit-r>
* %cvt/ri <bit-l>, <bit-r> * %cvt/rs <bit-l>, <bit-r>
* %cvt/vr <bit-l>, <bit-r>, <wid>
Copy a word from r to l, converting it from real to integer (ir) or Copy a word from r to l, converting it from real to signed integer (sr)
integer to real (ri) in the process. The source and destination may or signed integer to real (rs) in the process. The source and destination
be the same word address, leading to a convert in place. may be the same word address, leading to a convert in place. Precision
may be lost in the conversion.
* %cvt/ur <bit-l>, <bit-r>
* %cvt/ru <bit-l>, <bit-r>
Copy a word from r to l, converting it from real to unsigned integer (ur)
or signed integer to real (ru) in the process. The source and destination
may be the same word address, leading to a convert in place. Precision
may be lost in the conversion.
* %cvt/rv <bit-l>, <bit-r>, <wid>
* %cvt/rv/s <bit-l>, <bit-r>, <wid>
The %cvt/rv instruction converts a thread vector starting at <bit-r> and
with the width <wid> to a real word <bit-l>. Precision may be lost in
the conversion.
The %cvt/rv/s instruction is the same as %cvt/rv, but treats the thread
vector as a signed value.
* %cvt/vr <bit-l>, <bit-r>, <wid>
The %cvt/vr opcode converts a real word <bit-r> to a thread vector The %cvt/vr opcode converts a real word <bit-r> to a thread vector
starting at <bit-l> and with the width <wid>. Non-integer precision is starting at <bit-l> and with the width <wid>. Non-integer precision is

View File

@ -1774,7 +1774,43 @@ bool of_CMPZ(vthread_t thr, vvp_code_t cp)
return true; return true;
} }
bool of_CVT_IR(vthread_t thr, vvp_code_t cp) bool of_CVT_RS(vthread_t thr, vvp_code_t cp)
{
int64_t r = thr->words[cp->bit_idx[1]].w_int;
thr->words[cp->bit_idx[0]].w_real = (double)(r);
return true;
}
bool of_CVT_RU(vthread_t thr, vvp_code_t cp)
{
uint64_t r = thr->words[cp->bit_idx[1]].w_uint;
thr->words[cp->bit_idx[0]].w_real = (double)(r);
return true;
}
bool of_CVT_RV(vthread_t thr, vvp_code_t cp)
{
unsigned base = cp->bit_idx[1];
unsigned wid = cp->number;
vvp_vector4_t vector = vthread_bits_to_vector(thr, base, wid);
vector4_to_value(vector, thr->words[cp->bit_idx[0]].w_real, false);
return true;
}
bool of_CVT_RV_S(vthread_t thr, vvp_code_t cp)
{
unsigned base = cp->bit_idx[1];
unsigned wid = cp->number;
vvp_vector4_t vector = vthread_bits_to_vector(thr, base, wid);
vector4_to_value(vector, thr->words[cp->bit_idx[0]].w_real, true);
return true;
}
bool of_CVT_SR(vthread_t thr, vvp_code_t cp)
{ {
double r = thr->words[cp->bit_idx[1]].w_real; double r = thr->words[cp->bit_idx[1]].w_real;
thr->words[cp->bit_idx[0]].w_int = i64round(r); thr->words[cp->bit_idx[0]].w_int = i64round(r);
@ -1782,10 +1818,13 @@ bool of_CVT_IR(vthread_t thr, vvp_code_t cp)
return true; return true;
} }
bool of_CVT_RI(vthread_t thr, vvp_code_t cp) bool of_CVT_UR(vthread_t thr, vvp_code_t cp)
{ {
int64_t r = thr->words[cp->bit_idx[1]].w_int; double r = thr->words[cp->bit_idx[1]].w_real;
thr->words[cp->bit_idx[0]].w_real = (double)(r); if (r >= 0.0)
thr->words[cp->bit_idx[0]].w_uint = (uint64_t)floor(r+0.5);
else
thr->words[cp->bit_idx[0]].w_uint = (uint64_t)ceil(r-0.5);
return true; return true;
} }