From 1a3adbe9cddd40ec0dcdea7712d41964c2b1e0eb Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 5 Jan 2014 10:30:59 -0800 Subject: [PATCH] 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. --- tgt-vvp/draw_ufunc.c | 2 +- tgt-vvp/stmt_assign.c | 59 +++++++++++++++++++++++++++---------------- vvp/codes.h | 2 +- vvp/compile.cc | 4 +-- vvp/opcodes.txt | 19 +++++++++----- vvp/vthread.cc | 56 ++++++++++++++++++++++------------------ 6 files changed, 86 insertions(+), 56 deletions(-) diff --git a/tgt-vvp/draw_ufunc.c b/tgt-vvp/draw_ufunc.c index 3cc547e12..bc95b431a 100644 --- a/tgt-vvp/draw_ufunc.c +++ b/tgt-vvp/draw_ufunc.c @@ -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) diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index ac590a6d5..8c55119fd 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -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 (part_off_ex) { + 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; } diff --git a/vvp/codes.h b/vvp/codes.h index d006aca61..0ad6ea667 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -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); diff --git a/vvp/compile.cc b/vvp/compile.cc index c9dd60c31..47fc67a21 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -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} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index b5010c596..d54c3375e 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -1128,7 +1128,7 @@ register that contains the LSB of the vector, and the is the size of the vector. The width must exactly match the width of the signal. -* %set/av , , +* %set/av , , (XXXX Old definition) This sets a thread vector to an array word. The addresses an array device, and the , 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 , -* %store/vec4/off , , +* %store/vec4 , , +* %store/vec4a , , 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 bits and assigned to the -variable. It is an error for the value to be fewer then bits. +variable. It is an error for the value to be fewer then +bits. The 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 - to get a vector offset into the target vec4 variable. +The %store/vec4a is similar, but the target is an array of vec4, the + is an index register that contains the canonical address, and +the 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 is not necessary, and should be removed. diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 459494944..29b33f919 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -6035,47 +6035,55 @@ bool of_STORE_STRA(vthread_t thr, vvp_code_t cp) } /* - * %store/vec4 , + * %store/vec4 , , */ 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 , , - */ -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 (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); - vvp_send_vec4_pv(ptr, val, off, wid, sig->value_size(), thr->wt_context); + 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 , , + */ +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;