Properly implement casts from strings and dynamic arrays to vectors.

As discussed on iverilog-devel (2018-03-09), the existing implementation
(using Icarus-specific vpi functions) only worked with assignments to
simple variables, and could not be easily modified to work more generally.
So use the new vvp instructions added in the previous two commits.
This commit is contained in:
Martin Whitaker 2019-09-11 22:08:46 +01:00
parent 1aa22735ce
commit c066e2d15c
3 changed files with 30 additions and 39 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -158,7 +158,7 @@ NetExpr* cast_to_int2(NetExpr*expr, unsigned width)
NetExpr* cast_to_int4(NetExpr*expr, unsigned width)
{
// Special case: The expression is already LOGIC or BOOL
if (expr->expr_type() != IVL_VT_REAL)
if (expr->expr_type() == IVL_VT_LOGIC || expr->expr_type() == IVL_VT_BOOL)
return expr;
if (debug_elaborate)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 2013-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -1255,11 +1255,25 @@ static void draw_unary_vec4(ivl_expr_t expr)
local_count += 1;
break;
case 'v': /* Cast real to vec4 */
assert(ivl_expr_value(sub) == IVL_VT_REAL);
case 'v': /* Cast expression to vec4 */
switch (ivl_expr_value(sub)) {
case IVL_VT_REAL:
draw_eval_real(sub);
fprintf(vvp_out, " %%cvt/vr %u;\n", ivl_expr_width(expr));
break;
case IVL_VT_STRING:
draw_eval_string(sub);
fprintf(vvp_out, " %%cast/vec4/str %u;\n", ivl_expr_width(expr));
break;
case IVL_VT_DARRAY:
draw_eval_object(sub);
fprintf(vvp_out, " %%cast/vec4/dar %u;\n", ivl_expr_width(expr));
break;
default:
assert(0);
break;
}
break;
case '2': /* Cast expression to bool */
switch (ivl_expr_value(sub)) {
@ -1276,6 +1290,14 @@ static void draw_unary_vec4(ivl_expr_t expr)
draw_eval_real(sub);
fprintf(vvp_out, " %%cvt/vr %u;\n", ivl_expr_width(expr));
break;
case IVL_VT_STRING:
draw_eval_string(sub);
fprintf(vvp_out, " %%cast/vec4/str %u;\n", ivl_expr_width(expr));
break;
case IVL_VT_DARRAY:
draw_eval_object(sub);
fprintf(vvp_out, " %%cast/vec2/dar %u;\n", ivl_expr_width(expr));
break;
default:
assert(0);
break;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2011-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -515,37 +515,6 @@ static int show_stmt_assign_vector(ivl_statement_t net)
value pushed. */
fprintf(vvp_out, " %%cvt/vr %u;\n", wid);
} else if (ivl_expr_value(rval) == IVL_VT_STRING) {
/* Special case: string to vector casting */
ivl_lval_t lval = ivl_stmt_lval(net, 0);
fprintf(vvp_out, " %%vpi_call %u %u \"$ivl_string_method$to_vec\", v%p_0, v%p_0 {0 0 0};\n",
ivl_file_table_index(ivl_stmt_file(net)), ivl_stmt_lineno(net),
ivl_expr_signal(rval), ivl_lval_sig(lval));
if (slices) free(slices);
return 0;
} else if (ivl_expr_value(rval) == IVL_VT_DARRAY) {
/* Special case: dynamic array to vector casting */
ivl_lval_t lval = ivl_stmt_lval(net, 0);
void*rval_addr = NULL;
/* Even more special case: function call returning dynamic array */
if(ivl_expr_type(rval) == IVL_EX_UFUNC) {
rval_addr = ivl_scope_port(ivl_expr_def(rval), 0);
draw_ufunc_object(rval);
/* We do not need to store the result, it is going to be
converted to vector quite soon. */
fprintf(vvp_out, " %%pop/obj 1, 0; drop the result\n");
} else {
rval_addr = ivl_expr_signal(rval);
}
fprintf(vvp_out, " %%vpi_call %u %u \"$ivl_darray_method$to_vec\", v%p_0, v%p_0 {0 0 0};\n",
ivl_file_table_index(ivl_stmt_file(net)), ivl_stmt_lineno(net),
rval_addr, ivl_lval_sig(lval));
if (slices) free(slices);
return 0;
} else {
unsigned wid = ivl_stmt_lwidth(net);
draw_eval_vec4(rval);