vec4 support for ufuncs and ligical AND.
This commit is contained in:
parent
f89dbd48c8
commit
63fa44fa4a
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
fprintf(vvp_out, " %%jmp/1xz T_%u.%u, 5;\n", thread_count, lab_out);
|
if (ivl_expr_signed(expr))
|
||||||
|
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");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue