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)
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)

View File

@ -565,22 +565,44 @@ static void store_vec4_to_lval(ivl_statement_t net)
unsigned lwid = ivl_lval_width(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))
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) {
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 */
int offset_index = allocate_word();
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);
clr_word(offset_index);
} else {
/* No offset expression, so use simpler store function. */
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)
{
ivl_expr_t rval = ivl_stmt_rval(net);
struct vector_info res;
//struct vector_info res;
struct vector_info lres = {0, 0};
struct vec_slice_info*slices = 0;
@ -610,30 +632,25 @@ static int show_stmt_assign_vector(ivl_statement_t net)
assignment. */
unsigned wid = ivl_stmt_lwidth(net);
res.base = allocate_vector(wid);
res.wid = wid;
if (res.base == 0) {
fprintf(stderr, "%s:%u: vvp.tgt error: "
"Unable to allocate %u thread bits for "
"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);
/* Convert a calculated real value to a vec4 value of
the given width. We need to include the width of the
result because real values to not have any inherit
width. The real value will be popped, and a vec4
value pushed. */
fprintf(vvp_out, " %%cvt/vr %u;\n", wid);
} else {
draw_eval_vec4(rval, 0);
res.base = 0; // XXXX This is just to suppress the clr_vector below.
res.wid = 0;
//res.base = 0; // XXXX This is just to suppress the clr_vector below.
//res.wid = 0;
}
switch (ivl_stmt_opcode(net)) {
case 0:
store_vec4_to_lval(net);
break;
#if 0
// XXXX These need to be converted to vec4 style.
case '+':
if (res.base > 3) {
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",
res.base, lres.base, res.wid);
break;
#endif
default:
fprintf(vvp_out, "; UNSUPPORTED ASSIGNMENT OPCODE: %c\n", ivl_stmt_opcode(net));
assert(0);
@ -757,8 +774,6 @@ static int show_stmt_assign_vector(ivl_statement_t net)
if (slices)
free(slices);
if (res.base > 3)
clr_vector(res);
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_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_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_WR(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/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/vec4", of_STORE_VEC4, 2, {OA_FUNC_PTR,OA_BIT1, OA_NONE} },
{ "%store/vec4/off",of_STORE_VEC4_OFF,3, {OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
{ "%store/vec4", of_STORE_VEC4, 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/wr", of_SUB_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%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
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>
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
string string. The index is taken from signed index register 3.
* %store/vec4 <var-label>, <wid>
* %store/vec4/off <var-label>, <offset>, <wid>
* %store/vec4 <var-label>, <offset>, <wid>
* %store/vec4a <var-label>, <addr>, <offset>
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
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
<offset> to get a vector offset into the target vec4 variable.
The %store/vec4a is similar, but the target is an array of vec4, the
<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.

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)
{
/* 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_signal_value*sig = dynamic_cast<vvp_signal_value*> (cp->net->fil);
unsigned off_index = cp->bit_idx[0];
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();
assert(val.size() >= wid);
if (val.size() > 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);
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 l = thr->pop_vec4();
@ -6110,7 +6118,7 @@ bool of_SUB(vthread_t thr, vvp_code_t cp)
delete[]lva;
delete[]lvb;
vvp_vector4_t tmp(cp->number, BIT4_X);
vvp_vector4_t tmp(wid, BIT4_X);
thr->push_vec4(tmp);
return true;