static int show_stmt_assign_vector(ivl_statement_t net) { ivl_expr_t rval = ivl_stmt_rval(net); struct vector_info res; struct vector_info lres = {0, 0}; struct vec_slice_info*slices = 0; /* If this is a compressed assignment, then get the contents of the l-value. We need these values as part of the r-value calculation. */ if (ivl_stmt_opcode(net) != 0) { slices = calloc(ivl_stmt_lvals(net), sizeof(struct vec_slice_info)); lres = get_vec_from_lval(net, slices); } /* Handle the special case that the expression is a real value. Evaluate the real expression, then convert the result to a vector. Then store that vector into the l-value. */ if (ivl_expr_value(rval) == IVL_VT_REAL) { draw_eval_real(rval); /* This is the accumulated with of the l-value of the assignment. */ unsigned wid = ivl_stmt_lwidth(net); 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 " "r-value expression.\n", ivl_expr_file(rval), ivl_expr_lineno(rval), wid); vvp_errors += 1; } fprintf(vvp_out, " %%cvt/vr %u, %u;\n", res.base, res.wid); } else { res = draw_eval_expr(rval, 0); } switch (ivl_stmt_opcode(net)) { case 0: set_vec_to_lval(net, res); break; case '+': if (res.base > 3) { fprintf(vvp_out, " %%add %u, %u, %u;\n", res.base, lres.base, res.wid); clr_vector(lres); } else { fprintf(vvp_out, " %%add %u, %u, %u;\n", lres.base, res.base, res.wid); res.base = lres.base; } put_vec_to_lval(net, slices, res); break; case '-': fprintf(vvp_out, " %%sub %u, %u, %u;\n", lres.base, res.base, res.wid); fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base, lres.base, res.wid); clr_vector(lres); put_vec_to_lval(net, slices, res); break; case '*': if (res.base > 3) { fprintf(vvp_out, " %%mul %u, %u, %u;\n", res.base, lres.base, res.wid); clr_vector(lres); } else { fprintf(vvp_out, " %%mul %u, %u, %u;\n", lres.base, res.base, res.wid); res.base = lres.base; } put_vec_to_lval(net, slices, res); break; case '/': fprintf(vvp_out, " %%div%s %u, %u, %u;\n", ivl_expr_signed(rval)? "/s" : "", lres.base, res.base, res.wid); fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base, lres.base, res.wid); clr_vector(lres); put_vec_to_lval(net, slices, res); break; case '%': fprintf(vvp_out, " %%mod%s %u, %u, %u;\n", ivl_expr_signed(rval)? "/s" : "", lres.base, res.base, res.wid); fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base, lres.base, res.wid); clr_vector(lres); put_vec_to_lval(net, slices, res); break; case '&': if (res.base > 3) { fprintf(vvp_out, " %%and %u, %u, %u;\n", res.base, lres.base, res.wid); clr_vector(lres); } else { fprintf(vvp_out, " %%and %u, %u, %u;\n", lres.base, res.base, res.wid); res.base = lres.base; } put_vec_to_lval(net, slices, res); break; case '|': if (res.base > 3) { fprintf(vvp_out, " %%or %u, %u, %u;\n", res.base, lres.base, res.wid); clr_vector(lres); } else { fprintf(vvp_out, " %%or %u, %u, %u;\n", lres.base, res.base, res.wid); res.base = lres.base; } put_vec_to_lval(net, slices, res); break; case '^': if (res.base > 3) { fprintf(vvp_out, " %%xor %u, %u, %u;\n", res.base, lres.base, res.wid); clr_vector(lres); } else { fprintf(vvp_out, " %%xor %u, %u, %u;\n", lres.base, res.base, res.wid); res.base = lres.base; } put_vec_to_lval(net, slices, res); break; case 'l': /* lres <<= res */ fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", res.base, res.wid); fprintf(vvp_out, " %%shiftl/i0 %u, %u;\n", lres.base, res.wid); fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base, lres.base, res.wid); break; case 'r': /* lres >>= res */ fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", res.base, res.wid); fprintf(vvp_out, " %%shiftr/i0 %u, %u;\n", lres.base, res.wid); fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base, lres.base, res.wid); break; case 'R': /* lres >>>= res */ fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", res.base, res.wid); fprintf(vvp_out, " %%shiftr/s/i0 %u, %u;\n", lres.base, res.wid); fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base, lres.base, res.wid); break; default: fprintf(vvp_out, "; UNSUPPORTED ASSIGNMENT OPCODE: %c\n", ivl_stmt_opcode(net)); assert(0); break; } if (slices) free(slices); if (res.base > 3) clr_vector(res); return 0; }
static int show_stmt_assign_vector(ivl_statement_t net) { ivl_lval_t lval; ivl_expr_t rval = ivl_stmt_rval(net); ivl_memory_t mem; /* Handle the special case that the expression is a real value. Evaluate the real expression, then convert the result to a vector. Then store that vector into the l-value. */ if (ivl_expr_value(rval) == IVL_VT_REAL) { int word = draw_eval_real(rval); /* This is the accumulated with of the l-value of the assignment. */ unsigned wid = ivl_stmt_lwidth(net); struct vector_info vec; vec.base = allocate_vector(wid); vec.wid = wid; fprintf(vvp_out, " %%cvt/vr %u, %d, %u;\n", vec.base, word, vec.wid); clr_word(word); set_vec_to_lval(net, vec); clr_vector(vec); return 0; } /* Handle the special case that the r-value is a constant. We can generate the %set statement directly, without any worry about generating code to evaluate the r-value expressions. */ if (ivl_expr_type(rval) == IVL_EX_NUMBER) { unsigned lidx; const char*bits = ivl_expr_bits(rval); unsigned wid = ivl_expr_width(rval); unsigned cur_rbit = 0; for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) { unsigned skip_set = transient_id++; unsigned skip_set_flag = 0; unsigned idx; unsigned bit_limit = wid - cur_rbit; lval = ivl_stmt_lval(net, lidx); /* If there is a mux for the lval, calculate the value and write it into index0. */ if (ivl_lval_mux(lval)) { calculate_into_x0(ivl_lval_mux(lval)); /* Generate code to skip around the set if the index has X values. */ fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set); skip_set_flag = 1; } mem = ivl_lval_mem(lval); if (mem) { draw_memory_index_expr(mem, ivl_lval_idx(lval)); /* Generate code to skip around the set if the index has X values. */ fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set); skip_set_flag = 1; } if (bit_limit > ivl_lval_pins(lval)) bit_limit = ivl_lval_pins(lval); if (mem) { for (idx = 0 ; idx < bit_limit ; idx += 1) { set_to_memory(mem, idx, bitchar_to_idx(bits[cur_rbit])); cur_rbit += 1; } for (idx = bit_limit ; idx < ivl_lval_pins(lval) ; idx += 1) set_to_memory(mem, idx, 0); } else { idx = 0; while (idx < bit_limit) { unsigned cnt = 1; while (((idx + cnt) < bit_limit) && (bits[cur_rbit] == bits[cur_rbit+cnt])) cnt += 1; set_to_lvariable(lval, idx, bitchar_to_idx(bits[cur_rbit]), cnt); cur_rbit += cnt; idx += cnt; } if (bit_limit < ivl_lval_pins(lval)) { unsigned cnt = ivl_lval_pins(lval) - bit_limit; set_to_lvariable(lval, bit_limit, 0, cnt); } } if (skip_set_flag) { fprintf(vvp_out, "t_%u ;\n", skip_set); clear_expression_lookaside(); } } return 0; } { struct vector_info res = draw_eval_expr(rval, 0); set_vec_to_lval(net, res); if (res.base > 3) clr_vector(res); } return 0; }