From cc7187c1725ea09855e3a9002e7b32f8f4424576 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 4 May 2008 22:00:01 -0700 Subject: [PATCH] Add support for abs() in logic threads. Add the code generator code to handle the abs() function in signed logic. Handle some of the interesting special cases as well. --- tgt-stub/expression.c | 26 +++++++++++++++++++++++--- tgt-vvp/eval_expr.c | 26 ++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/tgt-stub/expression.c b/tgt-stub/expression.c index 2de7b787e..fe197c30a 100644 --- a/tgt-stub/expression.c +++ b/tgt-stub/expression.c @@ -160,6 +160,28 @@ static void show_ternary_expression(ivl_expr_t net, unsigned ind) } } +void show_unary_expression(ivl_expr_t net, unsigned ind) +{ + unsigned width = ivl_expr_width(net); + const char*sign = ivl_expr_signed(net)? "signed" : "unsigned"; + const char*vt = vt_type_string(net); + + char name[8]; + switch (ivl_expr_opcode(net)) { + default: + snprintf(name, sizeof name, "%c", ivl_expr_opcode(net)); + break; + + case 'm': + snprintf(name, sizeof name, "abs()"); + break; + } + + fprintf(out, "%*s\n", ind, "", + name, width, sign, vt); + show_expression(ivl_expr_oper1(net), ind+4); +} + void show_expression(ivl_expr_t net, unsigned ind) { unsigned idx; @@ -252,9 +274,7 @@ void show_expression(ivl_expr_t net, unsigned ind) break; case IVL_EX_UNARY: - fprintf(out, "%*s\n", ind, "", - ivl_expr_opcode(net), width, sign, vt); - show_expression(ivl_expr_oper1(net), ind+4); + show_unary_expression(net, ind); break; case IVL_EX_UFUNC: diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index 04848e572..bca49cc0a 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -2456,6 +2456,32 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid) } break; + case 'm': /* abs() */ + res = draw_eval_expr_wid(sub, wid, 0); + + if (!ivl_expr_signed(sub)) + break; + + if (res.base == 0 || res.base == 2 || res.base == 3) + break; + + /* Handle the special case of a -1 constant. Make the + result a 1. */ + if (res.base == 1) { + res.base = allocate_vector(wid); + fprintf(vvp_out, " %%movi %d, 1, %u;\n", + res.base, res.wid); + break; + } + + fprintf(vvp_out, " %%cmpi/s %d, 0, %u;\n", res.base, res.wid); + fprintf(vvp_out, " %%jmp/0xz T_%u.%u, 5;\n", thread_count, local_count); + fprintf(vvp_out, " %%inv %d, %u;\n", res.base, res.wid); + fprintf(vvp_out, " %%addi %d, 1, %u;\n", res.base, res.wid); + fprintf(vvp_out, "T_%u.%u ;\n", thread_count, local_count); + local_count += 1; + break; + default: fprintf(stderr, "vvp error: unhandled unary: %c\n", ivl_expr_opcode(exp));