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:
parent
13cad6f268
commit
b416176c4d
|
|
@ -266,7 +266,7 @@ void draw_eval_expr_into_integer(ivl_expr_t expr, unsigned ix)
|
|||
case IVL_VT_REAL:
|
||||
word = draw_eval_real(expr);
|
||||
clr_word(word);
|
||||
fprintf(vvp_out, " %%cvt/ir %u, %u;\n", ix, word);
|
||||
fprintf(vvp_out, " %%cvt/sr %u, %u;\n", ix, word);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -274,11 +274,37 @@ static int draw_realnum_real(ivl_expr_t expr)
|
|||
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)
|
||||
{
|
||||
struct vector_info sv;
|
||||
int res;
|
||||
const char*sign_flag = "";
|
||||
|
||||
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
|
||||
it as a vector, then convert the result to a real
|
||||
(via an index register) for the result. */
|
||||
sv = draw_eval_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);
|
||||
res = draw_real_logic_expr(expr, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -319,25 +335,6 @@ static int draw_sfunc_real(ivl_expr_t expr)
|
|||
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)
|
||||
{
|
||||
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);
|
||||
switch (ivl_signal_data_type(sig)) {
|
||||
case IVL_VT_LOGIC:
|
||||
return draw_signal_real_logic(expr);
|
||||
return draw_real_logic_expr(expr, 0);
|
||||
case IVL_VT_REAL:
|
||||
return draw_signal_real_real(expr);
|
||||
default:
|
||||
|
|
@ -439,41 +436,11 @@ static int draw_unary_real(ivl_expr_t expr)
|
|||
ivl_expr_t sube;
|
||||
int sub;
|
||||
|
||||
/* If the opcode is a ~ then the sub expression must not be a
|
||||
* real expression, so use vector evaluation and then convert
|
||||
/* If the opcode is a ~ or a ! then the sub expression must not be
|
||||
* a real expression, so use vector evaluation and then convert
|
||||
* that result to a real value. */
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
if ((ivl_expr_opcode(expr) == '~') || (ivl_expr_opcode(expr) == '!')) {
|
||||
return draw_real_logic_expr(expr, STUFF_OK_XZ);
|
||||
}
|
||||
|
||||
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
|
||||
* division to work correctly. */
|
||||
if (ivl_expr_value(expr) != IVL_VT_REAL) {
|
||||
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;
|
||||
return draw_real_logic_expr(expr, STUFF_OK_XZ);
|
||||
}
|
||||
|
||||
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",
|
||||
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 {
|
||||
fprintf(stderr, "XXXX Evaluate real expression (%d)\n",
|
||||
|
|
|
|||
|
|
@ -1455,7 +1455,7 @@ static int show_stmt_delayx(ivl_statement_t net, ivl_scope_t sscope)
|
|||
|
||||
case IVL_VT_REAL: {
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_CMPX(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_RI(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CVT_RS(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_DEASSIGN(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DEASSIGN_WR(vthread_t thr, vvp_code_t code);
|
||||
|
|
|
|||
|
|
@ -119,8 +119,12 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%cmp/z", of_CMPZ, 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} },
|
||||
{ "%cvt/ir", of_CVT_IR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%cvt/ri", of_CVT_RI, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%cvt/rs", of_CVT_RS, 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} },
|
||||
{ "%deassign",of_DEASSIGN,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%deassign/wr",of_DEASSIGN_WR,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
||||
* %cvt/ir <bit-l>, <bit-r>
|
||||
* %cvt/ri <bit-l>, <bit-r>
|
||||
* %cvt/vr <bit-l>, <bit-r>, <wid>
|
||||
* %cvt/sr <bit-l>, <bit-r>
|
||||
* %cvt/rs <bit-l>, <bit-r>
|
||||
|
||||
Copy a word from r to l, converting it from real to integer (ir) or
|
||||
integer to real (ri) in the process. The source and destination may
|
||||
be the same word address, leading to a convert in place.
|
||||
Copy a word from r to l, converting it from real to signed integer (sr)
|
||||
or signed integer to real (rs) 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/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
|
||||
starting at <bit-l> and with the width <wid>. Non-integer precision is
|
||||
|
|
|
|||
|
|
@ -1774,7 +1774,43 @@ bool of_CMPZ(vthread_t thr, vvp_code_t cp)
|
|||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
thr->words[cp->bit_idx[0]].w_real = (double)(r);
|
||||
double r = thr->words[cp->bit_idx[1]].w_real;
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue