Vec4 store to memories.

This also reworks the working of the %store/vec4 instruction to
take a part offset, and eliminate the %store/vec4/off instruction.
This commit is contained in:
Stephen Williams 2014-01-05 10:30:59 -08:00
parent 63fa44fa4a
commit 1a3adbe9cd
6 changed files with 86 additions and 56 deletions

View File

@ -36,7 +36,7 @@ static void function_argument_logic(ivl_signal_t port, ivl_expr_t expr)
if (ewidth < pwidth) if (ewidth < pwidth)
fprintf(vvp_out, " %%pad/u %u;\n", pwidth); fprintf(vvp_out, " %%pad/u %u;\n", pwidth);
fprintf(vvp_out, " %%store/vec4 v%p_0, %u;\n", port, pwidth); fprintf(vvp_out, " %%store/vec4 v%p_0, 0, %u;\n", port, pwidth);
} }
static void function_argument_real(ivl_signal_t port, ivl_expr_t expr) static void function_argument_real(ivl_signal_t port, ivl_expr_t expr)

View File

@ -565,22 +565,44 @@ static void store_vec4_to_lval(ivl_statement_t net)
unsigned lwid = ivl_lval_width(lval); unsigned lwid = ivl_lval_width(lval);
ivl_expr_t part_off_ex = ivl_lval_part_off(lval); ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
/* This is non-nil if the l-val is the word of a memory,
and nil otherwise. */
ivl_expr_t word_ex = ivl_lval_idx(lval);
if (lidx+1 < ivl_stmt_lvals(net)) if (lidx+1 < ivl_stmt_lvals(net))
fprintf(vvp_out, " %%split/vec4 %u;\n", lwid); fprintf(vvp_out, " %%split/vec4 %u;\n", lwid);
if (word_ex) {
/* Handle index into an array */
int word_index = allocate_word();
int part_index = 0;
/* Calculate the word address into word_index */
draw_eval_expr_into_integer(word_ex, word_index);
/* If there is a part_offset, calcualte it into part_index. */
if (part_off_ex) { if (part_off_ex) {
part_index = allocate_word();
draw_eval_expr_into_integer(part_off_ex, part_index);
}
fprintf(vvp_out, " %%store/vec4a v%p, %d, %d;\n",
lsig, word_index, part_index);
clr_word(word_index);
if (part_index)
clr_word(part_index);
} else if (part_off_ex) {
/* Dynamically calculated part offset */ /* Dynamically calculated part offset */
int offset_index = allocate_word(); int offset_index = allocate_word();
draw_eval_expr_into_integer(part_off_ex, offset_index); draw_eval_expr_into_integer(part_off_ex, offset_index);
fprintf(vvp_out, " %%store/vec4/off v%p_0, %d, %u;\n", fprintf(vvp_out, " %%store/vec4 v%p_0, %d, %u;\n",
lsig, offset_index, lwid); lsig, offset_index, lwid);
clr_word(offset_index); clr_word(offset_index);
} else { } else {
/* No offset expression, so use simpler store function. */ /* No offset expression, so use simpler store function. */
assert(lwid == ivl_signal_width(lsig)); assert(lwid == ivl_signal_width(lsig));
fprintf(vvp_out, " %%store/vec4 v%p_0, %u;\n", lsig, lwid); fprintf(vvp_out, " %%store/vec4 v%p_0, 0, %u;\n", lsig, lwid);
} }
} }
} }
@ -588,7 +610,7 @@ static void store_vec4_to_lval(ivl_statement_t net)
static int show_stmt_assign_vector(ivl_statement_t net) static int show_stmt_assign_vector(ivl_statement_t net)
{ {
ivl_expr_t rval = ivl_stmt_rval(net); ivl_expr_t rval = ivl_stmt_rval(net);
struct vector_info res; //struct vector_info res;
struct vector_info lres = {0, 0}; struct vector_info lres = {0, 0};
struct vec_slice_info*slices = 0; struct vec_slice_info*slices = 0;
@ -610,30 +632,25 @@ static int show_stmt_assign_vector(ivl_statement_t net)
assignment. */ assignment. */
unsigned wid = ivl_stmt_lwidth(net); unsigned wid = ivl_stmt_lwidth(net);
res.base = allocate_vector(wid); /* Convert a calculated real value to a vec4 value of
res.wid = wid; the given width. We need to include the width of the
result because real values to not have any inherit
if (res.base == 0) { width. The real value will be popped, and a vec4
fprintf(stderr, "%s:%u: vvp.tgt error: " value pushed. */
"Unable to allocate %u thread bits for " fprintf(vvp_out, " %%cvt/vr %u;\n", wid);
"r-value expression.\n", ivl_expr_file(rval),
ivl_expr_lineno(rval), wid);
vvp_errors += 1;
}
fprintf(vvp_out, " %%cvt/vr %u, %u;\n", res.base, res.wid);
} else { } else {
draw_eval_vec4(rval, 0); draw_eval_vec4(rval, 0);
res.base = 0; // XXXX This is just to suppress the clr_vector below. //res.base = 0; // XXXX This is just to suppress the clr_vector below.
res.wid = 0; //res.wid = 0;
} }
switch (ivl_stmt_opcode(net)) { switch (ivl_stmt_opcode(net)) {
case 0: case 0:
store_vec4_to_lval(net); store_vec4_to_lval(net);
break; break;
#if 0
// XXXX These need to be converted to vec4 style.
case '+': case '+':
if (res.base > 3) { if (res.base > 3) {
fprintf(vvp_out, " %%add %u, %u, %u;\n", fprintf(vvp_out, " %%add %u, %u, %u;\n",
@ -748,7 +765,7 @@ static int show_stmt_assign_vector(ivl_statement_t net)
fprintf(vvp_out, " %%mov %u, %u, %u;\n", fprintf(vvp_out, " %%mov %u, %u, %u;\n",
res.base, lres.base, res.wid); res.base, lres.base, res.wid);
break; break;
#endif
default: default:
fprintf(vvp_out, "; UNSUPPORTED ASSIGNMENT OPCODE: %c\n", ivl_stmt_opcode(net)); fprintf(vvp_out, "; UNSUPPORTED ASSIGNMENT OPCODE: %c\n", ivl_stmt_opcode(net));
assert(0); assert(0);
@ -757,8 +774,6 @@ static int show_stmt_assign_vector(ivl_statement_t net)
if (slices) if (slices)
free(slices); free(slices);
if (res.base > 3)
clr_vector(res);
return 0; return 0;
} }

View File

@ -221,7 +221,7 @@ extern bool of_STORE_REALA(vthread_t thr, vvp_code_t code);
extern bool of_STORE_STR(vthread_t thr, vvp_code_t code); extern bool of_STORE_STR(vthread_t thr, vvp_code_t code);
extern bool of_STORE_STRA(vthread_t thr, vvp_code_t code); extern bool of_STORE_STRA(vthread_t thr, vvp_code_t code);
extern bool of_STORE_VEC4(vthread_t thr, vvp_code_t code); extern bool of_STORE_VEC4(vthread_t thr, vvp_code_t code);
extern bool of_STORE_VEC4_OFF(vthread_t thr, vvp_code_t code); extern bool of_STORE_VEC4A(vthread_t thr, vvp_code_t code);
extern bool of_SUB(vthread_t thr, vvp_code_t code); extern bool of_SUB(vthread_t thr, vvp_code_t code);
extern bool of_SUB_WR(vthread_t thr, vvp_code_t code); extern bool of_SUB_WR(vthread_t thr, vvp_code_t code);
extern bool of_SUBI(vthread_t thr, vvp_code_t code); extern bool of_SUBI(vthread_t thr, vvp_code_t code);

View File

@ -267,8 +267,8 @@ static const struct opcode_table_s opcode_table[] = {
{ "%store/reala", of_STORE_REALA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} }, { "%store/reala", of_STORE_REALA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
{ "%store/str", of_STORE_STR, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%store/str", of_STORE_STR, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%store/stra", of_STORE_STRA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} }, { "%store/stra", of_STORE_STRA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
{ "%store/vec4", of_STORE_VEC4, 2, {OA_FUNC_PTR,OA_BIT1, OA_NONE} }, { "%store/vec4", of_STORE_VEC4, 3, {OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
{ "%store/vec4/off",of_STORE_VEC4_OFF,3, {OA_FUNC_PTR,OA_BIT1, OA_BIT2} }, { "%store/vec4a", of_STORE_VEC4A, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
{ "%sub", of_SUB, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%sub", of_SUB, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%sub/wr", of_SUB_WR, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%sub/wr", of_SUB_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },

View File

@ -1128,7 +1128,7 @@ register that contains the LSB of the vector, and the <wid> is the
size of the vector. The width must exactly match the width of the size of the vector. The width must exactly match the width of the
signal. signal.
* %set/av <array-label>, <bit>, <wid> * %set/av <array-label>, <bit>, <wid> (XXXX Old definition)
This sets a thread vector to an array word. The <array-label> This sets a thread vector to an array word. The <array-label>
addresses an array device, and the <bit>,<wid> describe a vector to be addresses an array device, and the <bit>,<wid> describe a vector to be
@ -1239,16 +1239,23 @@ The %store/stra targets an array.
The %store/dar/str is similar, but the target is a dynamic array of The %store/dar/str is similar, but the target is a dynamic array of
string string. The index is taken from signed index register 3. string string. The index is taken from signed index register 3.
* %store/vec4 <var-label>, <wid> * %store/vec4 <var-label>, <offset>, <wid>
* %store/vec4/off <var-label>, <offset>, <wid> * %store/vec4a <var-label>, <addr>, <offset>
Store a logic vector into the variable. The value (and its width) is Store a logic vector into the variable. The value (and its width) is
popped off the top of the stack and written to the variable. The value popped off the top of the stack and written to the variable. The value
is then optionally truncated to <wid> bits and assigned to the is then optionally truncated to <wid> bits and assigned to the
variable. It is an error for the value to be fewer then <wid> bits. variable. It is an error for the value to be fewer then <wid>
bits. The <offset> is the index register that contains a part offset
for writing into a part of the variable.
The %store/vec4/off is similar, but it uses the index register The %store/vec4a is similar, but the target is an array of vec4, the
<offset> to get a vector offset into the target vec4 variable. <addr> is an index register that contains the canonical address, and
the <offset> is an index register that contains the vector part
offset.
Both index registers can be 0, to mean a zero value instead of a zero
register.
NOTE: The <wid> is not necessary, and should be removed. NOTE: The <wid> is not necessary, and should be removed.

View File

@ -6035,47 +6035,55 @@ bool of_STORE_STRA(vthread_t thr, vvp_code_t cp)
} }
/* /*
* %store/vec4 <var-label>, <wid> * %store/vec4 <var-label>, <offset>, <wid>
*/ */
bool of_STORE_VEC4(vthread_t thr, vvp_code_t cp) bool of_STORE_VEC4(vthread_t thr, vvp_code_t cp)
{
/* Set the value into port 0 of the destination */
vvp_net_ptr_t ptr (cp->net, 0);
unsigned wid = cp->bit_idx[0];
vvp_vector4_t val = thr->pop_vec4();
assert(val.size() >= wid);
if (val.size() > wid)
val.resize(wid);
vvp_send_vec4(ptr, val, thr->wt_context);
return true;
}
/*
* %storevec4/off <var-label>, <offset>, <wid>
*/
bool of_STORE_VEC4_OFF(vthread_t thr, vvp_code_t cp)
{ {
vvp_net_ptr_t ptr(cp->net, 0); vvp_net_ptr_t ptr(cp->net, 0);
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (cp->net->fil); vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (cp->net->fil);
unsigned off_index = cp->bit_idx[0]; unsigned off_index = cp->bit_idx[0];
unsigned wid = cp->bit_idx[1]; unsigned wid = cp->bit_idx[1];
int off = thr->words[off_index].w_int; int off = off_index? thr->words[off_index].w_int : 0;
vvp_vector4_t val = thr->pop_vec4(); vvp_vector4_t val = thr->pop_vec4();
assert(val.size() >= wid); assert(val.size() >= wid);
if (val.size() > wid) if (val.size() > wid)
val.resize(wid); val.resize(wid);
if (off==0 && val.size()==sig->value_size())
vvp_send_vec4(ptr, val, thr->wt_context);
else
vvp_send_vec4_pv(ptr, val, off, wid, sig->value_size(), thr->wt_context); vvp_send_vec4_pv(ptr, val, off, wid, sig->value_size(), thr->wt_context);
return true; return true;
} }
bool of_SUB(vthread_t thr, vvp_code_t cp) /*
* %store/vec4a <var-label>, <addr>, <offset>
*/
bool of_STORE_VEC4A(vthread_t thr, vvp_code_t cp)
{
unsigned adr_index = cp->bit_idx[0];
unsigned off_index = cp->bit_idx[1];
vvp_vector4_t value = thr->pop_vec4();
long adr = adr_index? thr->words[adr_index].w_int : 0;
long off = off_index? thr->words[off_index].w_int : 0;
array_set_word(cp->array, adr, off, value);
return true;
}
/*
* %sub
* pop r;
* pop l;
* push l-r;
*/
bool of_SUB(vthread_t thr, vvp_code_t)
{ {
vvp_vector4_t r = thr->pop_vec4(); vvp_vector4_t r = thr->pop_vec4();
vvp_vector4_t l = thr->pop_vec4(); vvp_vector4_t l = thr->pop_vec4();
@ -6110,7 +6118,7 @@ bool of_SUB(vthread_t thr, vvp_code_t cp)
delete[]lva; delete[]lva;
delete[]lvb; delete[]lvb;
vvp_vector4_t tmp(cp->number, BIT4_X); vvp_vector4_t tmp(wid, BIT4_X);
thr->push_vec4(tmp); thr->push_vec4(tmp);
return true; return true;