From 96813f76c14264b277f41bae128d8a803fcf9a7e Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Fri, 11 Oct 2013 18:05:45 -0700 Subject: [PATCH] Generate code to implement array_pattern assignment to darray This implements the feature in the VVP code generator. --- tgt-vvp/stmt_assign.c | 74 +++++++++++++++++++++++++++++++++++++++++++ tgt-vvp/vvp_priv.h | 5 +++ 2 files changed, 79 insertions(+) diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index a54c61feb..cd9e10bf4 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -795,6 +795,74 @@ static int show_stmt_assign_sig_string(ivl_statement_t net) return 0; } +unsigned width_of_packed_type(ivl_type_t net) +{ + unsigned idx; + unsigned width = 1; + for (idx = 0 ; idx < ivl_type_packed_dimensions(net) ; idx += 1) { + int lsb = ivl_type_packed_lsb(net,idx); + int msb = ivl_type_packed_msb(net,idx); + if (lsb <= msb) + width *= msb - lsb + 1; + else + width *= lsb - msb + 1; + } + return width; +} + +/* + * This function handles the special case that we assign an array + * pattern to a dynamic array. Handle this by assigning each + * element. The array pattern will have a fixed size. + */ +static int show_stmt_assign_darray_pattern(ivl_statement_t net) +{ + int errors = 0; + ivl_lval_t lval = ivl_stmt_lval(net, 0); + ivl_expr_t rval = ivl_stmt_rval(net); + + ivl_signal_t var= ivl_lval_sig(lval); + ivl_type_t var_type= ivl_signal_net_type(var); + assert(ivl_type_base(var_type) == IVL_VT_DARRAY); + + ivl_type_t element_type = ivl_type_element(var_type); + unsigned idx; + struct vector_info rvec; + unsigned element_width = 1; + if (ivl_type_base(element_type) == IVL_VT_BOOL) + element_width = width_of_packed_type(element_type); + else if (ivl_type_base(element_type) == IVL_VT_LOGIC) + element_width = width_of_packed_type(element_type); + + assert(ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN); + for (idx = 0 ; idx < ivl_expr_parms(rval) ; idx += 1) { + switch (ivl_type_base(element_type)) { + case IVL_VT_BOOL: + case IVL_VT_LOGIC: + rvec = draw_eval_expr_wid(ivl_expr_parm(rval,idx), + element_width, STUFF_OK_XZ); + fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx); + fprintf(vvp_out, " %%set/dar v%p_0, %u, %u;\n", + var, rvec.base, rvec.wid); + + if (rvec.base >= 4) clr_vector(rvec); + break; + + case IVL_VT_REAL: + draw_eval_real(ivl_expr_parm(rval,idx)); + fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx); + fprintf(vvp_out, " %%store/dar/r v%p_0;\n", var); + break; + default: + fprintf(vvp_out, "; ERROR: show_stmt_assign_darray_pattern: type_base=%d not implemented\n", ivl_type_base(element_type)); + errors += 1; + break; + } + } + + return errors; +} + static int show_stmt_assign_sig_darray(ivl_statement_t net) { int errors = 0; @@ -845,6 +913,12 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net) if (rvec.base >= 4) clr_vector(rvec); + } else if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) { + /* There is no l-value mux, but the r-value is an array + pattern. This is a special case of an assignment to + elements of the l-value. */ + errors += show_stmt_assign_darray_pattern(net); + } else { /* There is no l-value mux, so this must be an assignment to the array as a whole. Evaluate the diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index e94a2364b..e382ba960 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -83,6 +83,11 @@ extern const char* vvp_signal_label(ivl_signal_t sig); extern unsigned width_of_nexus(ivl_nexus_t nex); extern ivl_variable_type_t data_type_of_nexus(ivl_nexus_t nex); +/* + * Calculate the width (in bits) of a packed type. + */ +extern unsigned width_of_packed_type(ivl_type_t net); + extern int can_elide_bufz(ivl_net_logic_t net, ivl_nexus_ptr_t nptr); /*