vec4 support for ufuncs and ligical AND.

This commit is contained in:
Stephen Williams 2014-01-05 17:15:30 +00:00
parent f89dbd48c8
commit 63fa44fa4a
5 changed files with 46 additions and 45 deletions

View File

@ -24,7 +24,6 @@
static void function_argument_logic(ivl_signal_t port, ivl_expr_t expr) static void function_argument_logic(ivl_signal_t port, ivl_expr_t expr)
{ {
struct vector_info res;
unsigned ewidth, pwidth; unsigned ewidth, pwidth;
/* ports cannot be arrays. */ /* ports cannot be arrays. */
@ -32,16 +31,12 @@ static void function_argument_logic(ivl_signal_t port, ivl_expr_t expr)
ewidth = ivl_expr_width(expr); ewidth = ivl_expr_width(expr);
pwidth = ivl_signal_width(port); pwidth = ivl_signal_width(port);
/* Just like a normal assignment the function arguments need to
* be evaluated at either their width or the argument width if
* it is larger. */
if (ewidth < pwidth) ewidth = pwidth;
res = draw_eval_expr_wid(expr, ewidth, 0);
/* We could have extra bits so only select the ones we need. */ draw_eval_vec4(expr, 0);
fprintf(vvp_out, " %%set/v v%p_0, %u, %u;\n", port, res.base, pwidth); if (ewidth < pwidth)
fprintf(vvp_out, " %%pad/u %u;\n", pwidth);
clr_vector(res); fprintf(vvp_out, " %%store/vec4 v%p_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)
@ -153,13 +148,10 @@ static void draw_ufunc_epilogue(ivl_expr_t expr)
* parameter 0 of the function definition. * parameter 0 of the function definition.
*/ */
struct vector_info draw_ufunc_expr(ivl_expr_t expr, unsigned wid) void draw_ufunc_vec4(ivl_expr_t expr)
{ {
unsigned swid = ivl_expr_width(expr);
ivl_scope_t def = ivl_expr_def(expr); ivl_scope_t def = ivl_expr_def(expr);
ivl_signal_t retval = ivl_scope_port(def, 0); ivl_signal_t retval = ivl_scope_port(def, 0);
struct vector_info res;
unsigned load_wid;
/* Take in arguments to function and call function code. */ /* Take in arguments to function and call function code. */
draw_ufunc_preamble(expr); draw_ufunc_preamble(expr);
@ -167,36 +159,10 @@ struct vector_info draw_ufunc_expr(ivl_expr_t expr, unsigned wid)
/* Fresh basic block starts after the join. */ /* Fresh basic block starts after the join. */
clear_expression_lookaside(); clear_expression_lookaside();
/* The return value is in a signal that has the name of the
expression. Load that into the thread and return the
vector result. */
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 function result.\n",
ivl_expr_file(expr), ivl_expr_lineno(expr), wid);
vvp_errors += 1;
return res;
}
assert(res.base != 0);
load_wid = swid;
if (load_wid > ivl_signal_width(retval))
load_wid = ivl_signal_width(retval);
assert(ivl_signal_dimensions(retval) == 0); assert(ivl_signal_dimensions(retval) == 0);
fprintf(vvp_out, " %%load/v %u, v%p_0, %u;\n", fprintf(vvp_out, " %%load/vec4 v%p_0;\n", retval);
res.base, retval, load_wid);
/* Pad the signal value with zeros. */
if (load_wid < wid)
pad_expr_in_place(expr, res, swid);
draw_ufunc_epilogue(expr); draw_ufunc_epilogue(expr);
return res;
} }
void draw_ufunc_real(ivl_expr_t expr) void draw_ufunc_real(ivl_expr_t expr)

View File

@ -3685,11 +3685,11 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t expr, unsigned wid,
case IVL_EX_SFUNC: case IVL_EX_SFUNC:
res = draw_sfunc_expr(expr, wid); res = draw_sfunc_expr(expr, wid);
break; break;
#if 0
case IVL_EX_UFUNC: case IVL_EX_UFUNC:
res = draw_ufunc_expr(expr, wid); res = draw_ufunc_expr(expr, wid);
break; break;
#endif
case IVL_EX_UNARY: case IVL_EX_UNARY:
res = draw_unary_expr(expr, wid); res = draw_unary_expr(expr, wid);
break; break;

View File

@ -157,6 +157,29 @@ static void draw_binary_vec4_compare(ivl_expr_t expr, int stuff_ok_flag)
} }
} }
static void draw_binary_vec4_land(ivl_expr_t expr, int stuff_ok_flag)
{
ivl_expr_t le = ivl_expr_oper1(expr);
ivl_expr_t re = ivl_expr_oper2(expr);
/* Push the left expression. Reduce it to a single bit if
necessary. */
draw_eval_vec4(le, STUFF_OK_XZ);
if (ivl_expr_width(le) > 1)
fprintf(vvp_out, " %%or/r;\n");
/* Now push the right expression. Again, reduce to a single
bit if necessasry. */
draw_eval_vec4(re, STUFF_OK_XZ);
if (ivl_expr_width(re) > 1)
fprintf(vvp_out, " %%or/r;\n");
fprintf(vvp_out, " %%and;\n");
if (ivl_expr_width(expr) > 1)
fprintf(vvp_out, " %%pad/u %u;\n", ivl_expr_width(expr));
}
static void draw_binary_vec4_le_real(ivl_expr_t expr) static void draw_binary_vec4_le_real(ivl_expr_t expr)
{ {
ivl_expr_t le = ivl_expr_oper1(expr); ivl_expr_t le = ivl_expr_oper1(expr);
@ -312,6 +335,10 @@ static void draw_binary_vec4_lrs(ivl_expr_t expr, int stuff_ok_flag)
static void draw_binary_vec4(ivl_expr_t expr, int stuff_ok_flag) static void draw_binary_vec4(ivl_expr_t expr, int stuff_ok_flag)
{ {
switch (ivl_expr_opcode(expr)) { switch (ivl_expr_opcode(expr)) {
case 'a': /* Logical && */
draw_binary_vec4_land(expr, stuff_ok_flag);
break;
case '+': case '+':
case '-': case '-':
case '*': case '*':
@ -618,6 +645,10 @@ void draw_eval_vec4(ivl_expr_t expr, int stuff_ok_flag)
draw_ternary_vec4(expr, stuff_ok_flag); draw_ternary_vec4(expr, stuff_ok_flag);
return; return;
case IVL_EX_UFUNC:
draw_ufunc_vec4(expr);
return;
case IVL_EX_UNARY: case IVL_EX_UNARY:
draw_unary_vec4(expr, stuff_ok_flag); draw_unary_vec4(expr, stuff_ok_flag);
return; return;

View File

@ -104,7 +104,7 @@ extern int draw_scope(ivl_scope_t scope, ivl_scope_t parent);
extern void draw_lpm_mux(ivl_lpm_t net); extern void draw_lpm_mux(ivl_lpm_t net);
extern struct vector_info draw_ufunc_expr(ivl_expr_t expr, unsigned wid); extern void draw_ufunc_vec4(ivl_expr_t expr);
extern void draw_ufunc_real(ivl_expr_t expr); extern void draw_ufunc_real(ivl_expr_t expr);
extern void draw_ufunc_string(ivl_expr_t expr); extern void draw_ufunc_string(ivl_expr_t expr);
extern void draw_ufunc_object(ivl_expr_t expr); extern void draw_ufunc_object(ivl_expr_t expr);

View File

@ -1654,11 +1654,15 @@ static int show_stmt_repeat(ivl_statement_t net, ivl_scope_t sscope)
/* Calculate the repeat count onto the top of the vec4 stack. */ /* Calculate the repeat count onto the top of the vec4 stack. */
draw_eval_vec4(expr, STUFF_OK_XZ); draw_eval_vec4(expr, STUFF_OK_XZ);
/* Test that 0 < expr */ /* Test that 0 < expr, escape if expr <= 0. If the expr is
unsigned, then we only need to try to escape if expr==0 as
it will never be <0. */
fprintf(vvp_out, "T_%u.%u %%dup/vec4;\n", thread_count, lab_top); fprintf(vvp_out, "T_%u.%u %%dup/vec4;\n", thread_count, lab_top);
fprintf(vvp_out, " %%pushi/vec4 0, 0, %u;\n", ivl_expr_width(expr)); fprintf(vvp_out, " %%pushi/vec4 0, 0, %u;\n", ivl_expr_width(expr));
fprintf(vvp_out, " %%cmp/%s;\n", sign); fprintf(vvp_out, " %%cmp/%s;\n", sign);
if (ivl_expr_signed(expr))
fprintf(vvp_out, " %%jmp/1xz T_%u.%u, 5;\n", thread_count, lab_out); fprintf(vvp_out, " %%jmp/1xz T_%u.%u, 5;\n", thread_count, lab_out);
fprintf(vvp_out, " %%jmp/1 T_%u.%u, 4;\n", thread_count, lab_out);
/* This adds -1 (all ones in 2's complement) to the count. */ /* This adds -1 (all ones in 2's complement) to the count. */
fprintf(vvp_out, " %%pushi/vec4 1, 0, %u;\n", ivl_expr_width(expr)); fprintf(vvp_out, " %%pushi/vec4 1, 0, %u;\n", ivl_expr_width(expr));
fprintf(vvp_out, " %%sub;\n"); fprintf(vvp_out, " %%sub;\n");