Wrap up vecc4 support for left/right shift expressions.
This commit is contained in:
parent
6a93b6a7e4
commit
b0a9430e98
|
|
@ -1294,152 +1294,6 @@ static struct vector_info draw_binary_expr_logic(ivl_expr_t expr,
|
|||
return lv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw code to evaluate the << expression. Use the %shiftl/i0
|
||||
* or %shiftr/i0 instruction to do the real work of shifting. This
|
||||
* means that I can handle both left and right shifts in this
|
||||
* function, with the only difference the opcode I generate at the
|
||||
* end.
|
||||
*/
|
||||
static struct vector_info draw_binary_expr_lrs(ivl_expr_t expr, unsigned wid)
|
||||
{
|
||||
ivl_expr_t le = ivl_expr_oper1(expr);
|
||||
ivl_expr_t re = ivl_expr_oper2(expr);
|
||||
const char*opcode = "?";
|
||||
|
||||
struct vector_info lv;
|
||||
|
||||
/* Evaluate the expression that is to be shifted. */
|
||||
switch (ivl_expr_opcode(expr)) {
|
||||
|
||||
case 'l': /* << (left shift) */
|
||||
lv = draw_eval_expr_wid(le, wid, 0);
|
||||
|
||||
/* Shifting 0 gets 0, if we can be sure the shift value
|
||||
contains no 'x' or 'z' bits. */
|
||||
if ((lv.base == 0) && (ivl_expr_value(re) == IVL_VT_BOOL))
|
||||
return lv;
|
||||
|
||||
if (lv.base < 4) {
|
||||
struct vector_info tmp;
|
||||
tmp.base = allocate_vector(lv.wid);
|
||||
tmp.wid = lv.wid;
|
||||
if (tmp.base == 0) {
|
||||
fprintf(stderr, "%s:%u: vvp.tgt error: "
|
||||
"Unable to allocate %u thread bits "
|
||||
"for result of left shift (<<).\n",
|
||||
ivl_expr_file(expr), ivl_expr_lineno(expr),
|
||||
wid);
|
||||
vvp_errors += 1;
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
||||
tmp.base, lv.base, lv.wid);
|
||||
lv = tmp;
|
||||
}
|
||||
opcode = "%shiftl";
|
||||
break;
|
||||
|
||||
case 'r': /* >> (unsigned right shift) */
|
||||
|
||||
/* with the right shift, there may be high bits that are
|
||||
shifted into the desired width of the expression, so
|
||||
we let the expression size itself, if it is bigger
|
||||
then what is requested of us. */
|
||||
if (wid > ivl_expr_width(le)) {
|
||||
lv = draw_eval_expr_wid(le, wid, 0);
|
||||
} else {
|
||||
lv = draw_eval_expr_wid(le, ivl_expr_width(le), 0);
|
||||
}
|
||||
|
||||
/* Shifting 0 gets 0, if we can be sure the shift value
|
||||
contains no 'x' or 'z' bits. */
|
||||
if ((lv.base == 0) && (ivl_expr_value(re) == IVL_VT_BOOL))
|
||||
return lv;
|
||||
|
||||
if (lv.base < 4) {
|
||||
struct vector_info tmp;
|
||||
tmp.base = allocate_vector(lv.wid);
|
||||
tmp.wid = lv.wid;
|
||||
if (tmp.base == 0) {
|
||||
fprintf(stderr, "%s:%u: vvp.tgt error: "
|
||||
"Unable to allocate %u thread bits "
|
||||
"for result of right shift (>>).\n",
|
||||
ivl_expr_file(expr), ivl_expr_lineno(expr),
|
||||
lv.wid);
|
||||
vvp_errors += 1;
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
||||
tmp.base, lv.base, lv.wid);
|
||||
lv = tmp;
|
||||
}
|
||||
opcode = "%shiftr";
|
||||
break;
|
||||
|
||||
case 'R': /* >>> (signed right shift) */
|
||||
|
||||
/* with the right shift, there may be high bits that are
|
||||
shifted into the desired width of the expression, so
|
||||
we let the expression size itself, if it is bigger
|
||||
then what is requested of us. */
|
||||
if (wid > ivl_expr_width(le)) {
|
||||
lv = draw_eval_expr_wid(le, wid, 0);
|
||||
} else {
|
||||
lv = draw_eval_expr_wid(le, ivl_expr_width(le), 0);
|
||||
}
|
||||
|
||||
/* Shifting 0 gets 0, if we can be sure the shift value
|
||||
contains no 'x' or 'z' bits. */
|
||||
if ((lv.base == 0) && (ivl_expr_value(re) == IVL_VT_BOOL))
|
||||
return lv;
|
||||
|
||||
/* Similarly, sign extending any constant bit begets itself,
|
||||
if this expression is signed. */
|
||||
if ((lv.base < 4) && ivl_expr_signed(expr)
|
||||
&& (ivl_expr_value(re) == IVL_VT_BOOL))
|
||||
return lv;
|
||||
|
||||
if (lv.base < 4) {
|
||||
struct vector_info tmp;
|
||||
tmp.base = allocate_vector(lv.wid);
|
||||
tmp.wid = lv.wid;
|
||||
if (tmp.base == 0) {
|
||||
fprintf(stderr, "%s:%u: vvp.tgt error: "
|
||||
"Unable to allocate %u thread bits "
|
||||
"for result of right shift (>>>).\n",
|
||||
ivl_expr_file(expr), ivl_expr_lineno(expr),
|
||||
lv.wid);
|
||||
vvp_errors += 1;
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
||||
tmp.base, lv.base, lv.wid);
|
||||
lv = tmp;
|
||||
}
|
||||
|
||||
if (ivl_expr_signed(expr))
|
||||
opcode = "%shiftr/s";
|
||||
else
|
||||
opcode = "%shiftr";
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* Figure out the shift amount and load that into the index
|
||||
register. The value may be a constant, or may need to be
|
||||
evaluated at run time. */
|
||||
eval_logic_into_integer(re,0);
|
||||
|
||||
fprintf(vvp_out, " %s/i0 %u, %u;\n", opcode, lv.base, lv.wid);
|
||||
|
||||
if (lv.base >= 8)
|
||||
save_expression_lookaside(lv.base, expr, lv.wid);
|
||||
|
||||
return lv;
|
||||
}
|
||||
|
||||
static struct vector_info draw_load_add_immediate(ivl_expr_t le,
|
||||
ivl_expr_t re,
|
||||
|
|
@ -1781,12 +1635,6 @@ static struct vector_info draw_binary_expr(ivl_expr_t expr,
|
|||
rv = draw_binary_expr_arith(expr, wid);
|
||||
break;
|
||||
|
||||
case 'l': /* << */
|
||||
case 'r': /* >> */
|
||||
case 'R': /* >>> */
|
||||
rv = draw_binary_expr_lrs(expr, wid);
|
||||
break;
|
||||
|
||||
case 'o': /* || (logical or) */
|
||||
rv = draw_binary_expr_lor(expr, wid, stuff_ok_flag);
|
||||
stuff_ok_used_flag = 1;
|
||||
|
|
@ -1802,7 +1650,7 @@ static struct vector_info draw_binary_expr(ivl_expr_t expr,
|
|||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp.tgt error: unsupported binary (%c)\n",
|
||||
fprintf(stderr, "vvp.tgt error: draw_binary_expr: unsupported binary (%c)\n",
|
||||
ivl_expr_opcode(expr));
|
||||
assert(0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -336,7 +336,10 @@ static void draw_binary_vec4_lrs(ivl_expr_t expr, int stuff_ok_flag)
|
|||
fprintf(vvp_out, " %%shiftr %u;\n", use_index_reg);
|
||||
break;
|
||||
case 'R': /* >>> */
|
||||
fprintf(vvp_out, " %%shiftrs %u;\n", use_index_reg);
|
||||
if (ivl_expr_signed(le))
|
||||
fprintf(vvp_out, " %%shiftr/s %u;\n", use_index_reg);
|
||||
else
|
||||
fprintf(vvp_out, " %%shiftr %u;\n", use_index_reg);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
|
|
|
|||
|
|
@ -1168,29 +1168,6 @@ The index may be signed, and if less than 0, the beginning bits are
|
|||
not assigned. Also, if the bits go beyond the end of the signal, those
|
||||
bits are not written anywhere.
|
||||
|
||||
|
||||
* %shiftl/i0 <bit>, <wid> (XXXX Old implementation)
|
||||
|
||||
This instruction shifts the vector left (towards more significant
|
||||
bits) by the amount in index register 0. The <bit> is the address of
|
||||
the LSB of the vector, and <wid> the width of the vector. The shift is
|
||||
done in place. Zero values are shifted in.
|
||||
|
||||
For a negative shift the value is padded with 'bx.
|
||||
|
||||
* %shiftr/i0 <bit>, <wid> (XXXX Old implementation)
|
||||
* %shiftr/s/i0 <bit>, <wid> (XXXX Old implementation)
|
||||
|
||||
This instruction shifts the vector right (towards the less significant
|
||||
bits) by the amount in the index register 0. The <bit> is the address
|
||||
of the LSB of the vector, and <wid> is the width of the vector. The
|
||||
shift is done in place.
|
||||
|
||||
%shiftr/i0 is an unsigned down shift, so zeros are shifted into the
|
||||
top bits. %shiftr/s/i0 is a signed shift, so the value is sign-extended.
|
||||
|
||||
For a negative shift %shiftr/i0 will pad the value with 'bx.
|
||||
|
||||
* %shiftl <idx>
|
||||
* %shiftr <idx>
|
||||
* %shiftr/s <idx>
|
||||
|
|
@ -1199,6 +1176,12 @@ These instructions shift the top value in the vec4 stack left (towards
|
|||
MSB) or right, possibly signed. The <idx> is the address of the index
|
||||
register that contains the amount to shift.
|
||||
|
||||
The instruction also checks flag bit 4. If it is true, the result is
|
||||
replaced with X instead of a shifted result. This is intended to
|
||||
detect that the index contents were not valid.
|
||||
|
||||
For a negative shift, %shiftr will pad the vlaue with 'bx.
|
||||
|
||||
* %split/vec4 <wid>
|
||||
|
||||
Pull the top vec4 vector from the stack and split it into two
|
||||
|
|
|
|||
182
vvp/vthread.cc
182
vvp/vthread.cc
|
|
@ -5491,54 +5491,6 @@ bool of_SET_X0(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool of_SHIFTL_I0(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
int base = cp->bit_idx[0];
|
||||
int wid = cp->number;
|
||||
int shift = thr->words[0].w_int;
|
||||
|
||||
assert(base >= 4);
|
||||
thr_check_addr(thr, base+wid-1);
|
||||
|
||||
if (thr_get_bit(thr, 4) == BIT4_1) {
|
||||
// The result is 'bx if the shift amount is undefined.
|
||||
vvp_vector4_t tmp (wid, BIT4_X);
|
||||
thr->bits4.set_vec(base, tmp);
|
||||
|
||||
} else if (shift >= wid) {
|
||||
// Shift is so far that all value is shifted out. Write
|
||||
// in a constant 0 result.
|
||||
vvp_vector4_t tmp (wid, BIT4_0);
|
||||
thr->bits4.set_vec(base, tmp);
|
||||
|
||||
} else if (shift > 0) {
|
||||
vvp_vector4_t tmp (thr->bits4, base, wid-shift);
|
||||
thr->bits4.set_vec(base+shift, tmp);
|
||||
|
||||
// Fill zeros on the bottom
|
||||
vvp_vector4_t fil (shift, BIT4_0);
|
||||
thr->bits4.set_vec(base, fil);
|
||||
|
||||
} else if (shift <= -wid) {
|
||||
vvp_vector4_t tmp (wid, BIT4_X);
|
||||
thr->bits4.set_vec(base, tmp);
|
||||
|
||||
} else if (shift < 0) {
|
||||
// For a negative shift we pad with 'bx.
|
||||
int idx;
|
||||
for (idx = 0 ; (idx-shift) < wid ; idx += 1) {
|
||||
unsigned src = base + idx - shift;
|
||||
unsigned dst = base + idx;
|
||||
thr_put_bit(thr, dst, thr_get_bit(thr, src));
|
||||
}
|
||||
for ( ; idx < wid ; idx += 1)
|
||||
thr_put_bit(thr, base+idx, BIT4_X);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* %shiftl <idx>
|
||||
*/
|
||||
|
|
@ -5581,61 +5533,6 @@ bool of_SHIFTL(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* This is an unsigned right shift:
|
||||
*
|
||||
* %shiftr/i0 <bit>, <wid>
|
||||
*
|
||||
* The vector at address <bit> with width <wid> is shifted right a
|
||||
* number of bits stored in index/word register 0.
|
||||
*/
|
||||
bool of_SHIFTR_I0(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
int base = cp->bit_idx[0];
|
||||
int wid = cp->number;
|
||||
int shift = thr->words[0].w_int;
|
||||
|
||||
assert(base >= 4);
|
||||
thr_check_addr(thr, base+wid-1);
|
||||
|
||||
if (thr_get_bit(thr, 4) == BIT4_1) {
|
||||
// The result is 'bx if the shift amount is undefined.
|
||||
vvp_vector4_t tmp (wid, BIT4_X);
|
||||
thr->bits4.set_vec(base, tmp);
|
||||
|
||||
} else if (shift > wid) {
|
||||
// Shift so far that the entire vector is shifted out.
|
||||
vvp_vector4_t tmp (wid, BIT4_0);
|
||||
thr->bits4.set_vec(base, tmp);
|
||||
|
||||
} else if (shift > 0) {
|
||||
// The mov method should handle overlapped source/dest
|
||||
thr->bits4.mov(base, base+shift, wid-shift);
|
||||
|
||||
vvp_vector4_t tmp (shift, BIT4_0);
|
||||
thr->bits4.set_vec(base+wid-shift, tmp);
|
||||
|
||||
} else if (shift < -wid) {
|
||||
// Negative shift is so far that all the value is shifted out.
|
||||
// Write in a constant 'bx result.
|
||||
vvp_vector4_t tmp (wid, BIT4_X);
|
||||
thr->bits4.set_vec(base, tmp);
|
||||
|
||||
} else if (shift < 0) {
|
||||
|
||||
// For a negative shift we pad with 'bx.
|
||||
vvp_vector4_t tmp (thr->bits4, base, wid+shift);
|
||||
thr->bits4.set_vec(base-shift, tmp);
|
||||
|
||||
vvp_vector4_t fil (-shift, BIT4_X);
|
||||
thr->bits4.set_vec(base, fil);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* %shiftr <idx>
|
||||
* This is an unsigned right shift. The <idx> is a number that selects
|
||||
|
|
@ -5678,53 +5575,42 @@ bool of_SHIFTR(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool of_SHIFTR_S_I0(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
int base = cp->bit_idx[0];
|
||||
int wid = cp->number;
|
||||
int shift = thr->words[0].w_int;
|
||||
vvp_bit4_t sign = thr_get_bit(thr, base+wid-1);
|
||||
|
||||
if (thr_get_bit(thr, 4) == BIT4_1) {
|
||||
// The result is 'bx if the shift amount is undefined.
|
||||
vvp_vector4_t tmp (wid, BIT4_X);
|
||||
thr->bits4.set_vec(base, tmp);
|
||||
} else if (shift >= wid) {
|
||||
for (int idx = 0 ; idx < wid ; idx += 1)
|
||||
thr_put_bit(thr, base+idx, sign);
|
||||
|
||||
} else if (shift > 0) {
|
||||
for (int idx = 0 ; idx < (wid-shift) ; idx += 1) {
|
||||
unsigned src = base + idx + shift;
|
||||
unsigned dst = base + idx;
|
||||
thr_put_bit(thr, dst, thr_get_bit(thr, src));
|
||||
}
|
||||
for (int idx = (wid-shift) ; idx < wid ; idx += 1)
|
||||
thr_put_bit(thr, base+idx, sign);
|
||||
|
||||
} else if (shift < -wid) {
|
||||
// Negative shift is so far that all the value is
|
||||
// shifted out. Write in a constant 'bx result.
|
||||
vvp_vector4_t tmp (wid, BIT4_X);
|
||||
thr->bits4.set_vec(base, tmp);
|
||||
|
||||
} else if (shift < 0) {
|
||||
|
||||
// For a negative shift we pad with 'bx.
|
||||
vvp_vector4_t tmp (thr->bits4, base, wid+shift);
|
||||
thr->bits4.set_vec(base-shift, tmp);
|
||||
|
||||
vvp_vector4_t fil (-shift, BIT4_X);
|
||||
thr->bits4.set_vec(base, fil);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* %shiftr/s <wid>
|
||||
*/
|
||||
bool of_SHIFTR_S(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
fprintf(stderr, "XXXX of_SHIFTR_S not implemented\n");
|
||||
int use_index = cp->number;
|
||||
int shift = thr->words[use_index].w_int;
|
||||
|
||||
vvp_vector4_t val = thr->pop_vec4();
|
||||
int wid = val.size();
|
||||
|
||||
vvp_bit4_t sign_bit = val.value(val.size()-1);
|
||||
|
||||
if (thr->flags[4] == BIT4_1) {
|
||||
val = vvp_vector4_t(wid, BIT4_X);
|
||||
|
||||
} else if (shift > wid) {
|
||||
val = vvp_vector4_t(wid, sign_bit);
|
||||
|
||||
} else if (shift > 0) {
|
||||
val.mov(0, shift, wid-shift);
|
||||
|
||||
vvp_vector4_t tmp (shift, sign_bit);
|
||||
val.set_vec(wid-shift, tmp);
|
||||
|
||||
} else if (shift < -wid) {
|
||||
val = vvp_vector4_t(wid, BIT4_X);
|
||||
|
||||
} else if (shift < 0) {
|
||||
int use_shift = -shift;
|
||||
val.mov(use_shift, 0, wid-use_shift);
|
||||
vvp_vector4_t tmp(use_shift, BIT4_X);
|
||||
val.set_vec(0, tmp);
|
||||
}
|
||||
|
||||
thr->push_vec4(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue