/* * An assignment is one of a possible list of l-values to a behavioral * assignment. Each l-value is either a part select of a signal or a * non-constant bit select. */ static void show_assign_lval(ivl_lval_t lval) { ivl_nexus_t nex; ivl_signal_t sig=NULL; unsigned idx; unsigned lsb=0; assert(ivl_lval_mux(lval) == 0); assert(ivl_lval_mem(lval) == 0); nex = ivl_lval_pin(lval, 0); for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) { unsigned pin; ivl_nexus_ptr_t ptr; ptr = ivl_nexus_ptr(nex, idx); sig = ivl_nexus_ptr_sig(ptr); if (sig == 0) continue; lsb = ivl_nexus_ptr_pin(ptr); for (pin = 1 ; pin < ivl_lval_pins(lval) ; pin += 1) { if (ivl_signal_pin(sig, lsb+pin) != ivl_lval_pin(lval,pin)) break; } if (pin < ivl_lval_pins(lval)) continue; break; } assert(sig); if ((lsb > 0) || (lsb + ivl_lval_pins(lval)) < ivl_signal_pins(sig)) { fprintf(out, "%s[%u:%u]", ivl_signal_name(sig), lsb+ivl_lval_pins(lval)-1, lsb); } else { fprintf(out, "%s", ivl_signal_name(sig)); } }
static int show_stmt_assign_nb(ivl_statement_t net) { ivl_lval_t lval; ivl_expr_t rval = ivl_stmt_rval(net); ivl_expr_t del = ivl_stmt_delay_expr(net); ivl_memory_t mem; unsigned long delay = 0; /* Catch the case we are assigning to a real/word l-value. Handle that elsewhere. */ if (ivl_lval_var(ivl_stmt_lval(net, 0))) { return show_stmt_assign_nb_var(net); } if (del && (ivl_expr_type(del) == IVL_EX_ULONG)) { delay = ivl_expr_uvalue(del); del = 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; if (del != 0) calculate_into_x1(del); 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)); 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)); 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) { assign_to_memory(mem, idx, bitchar_to_idx(bits[cur_rbit]), delay); cur_rbit += 1; } for (idx = bit_limit ; idx < ivl_lval_pins(lval) ; idx += 1) { assign_to_memory(mem, idx, 0, delay); } } else if ((del == 0) && (bit_limit > 2)) { /* We have a vector, but no runtime calculated delays, to try to use vector assign instructions. */ idx = 0; while (idx < bit_limit) { unsigned wid = 0; do { wid += 1; if ((idx + wid) == bit_limit) break; } while (bits[cur_rbit] == bits[cur_rbit+wid]); switch (wid) { case 1: assign_to_lvariable(lval, idx, bitchar_to_idx(bits[cur_rbit]), delay, 0); break; case 2: assign_to_lvariable(lval, idx, bitchar_to_idx(bits[cur_rbit]), delay, 0); assign_to_lvariable(lval, idx+1, bitchar_to_idx(bits[cur_rbit]), delay, 0); break; default: assign_to_lvector(lval, idx, bitchar_to_idx(bits[cur_rbit]), delay, wid); break; } idx += wid; cur_rbit += wid; } if (bit_limit < ivl_lval_pins(lval)) { unsigned wid = ivl_lval_pins(lval) - bit_limit; assign_to_lvector(lval, bit_limit, 0, delay, wid); } } else { for (idx = 0 ; idx < bit_limit ; idx += 1) { if (del != 0) assign_to_lvariable(lval, idx, bitchar_to_idx(bits[cur_rbit]), 1, 1); else assign_to_lvariable(lval, idx, bitchar_to_idx(bits[cur_rbit]), delay, 0); cur_rbit += 1; } for (idx = bit_limit ; idx < ivl_lval_pins(lval) ; idx += 1) { if (del != 0) assign_to_lvariable(lval, idx, 0, 1, 1); else assign_to_lvariable(lval, idx, 0, delay, 0); } } 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); unsigned wid = res.wid; unsigned lidx; unsigned cur_rbit = 0; if (del != 0) calculate_into_x1(del); 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)); 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)); 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 ((bit_limit > 2) && (mem == 0) && (del == 0)) { unsigned bidx = res.base < 4 ? res.base : (res.base+cur_rbit); assign_to_lvector(lval, 0, bidx, delay, bit_limit); cur_rbit += bit_limit; } else { for (idx = 0 ; idx < bit_limit ; idx += 1) { unsigned bidx = res.base < 4 ? res.base : (res.base+cur_rbit); if (mem) assign_to_memory(mem, idx, bidx, delay); else if (del != 0) assign_to_lvariable(lval, idx, bidx, 1, 1); else assign_to_lvariable(lval, idx, bidx, delay, 0); cur_rbit += 1; } } for (idx = bit_limit; idx < ivl_lval_pins(lval); idx += 1) if (mem) assign_to_memory(mem, idx, 0, delay); else if (del != 0) assign_to_lvariable(lval, idx, 0, 1, 1); else assign_to_lvariable(lval, idx, 0, delay, 0); if (skip_set_flag) { fprintf(vvp_out, "t_%u ;\n", skip_set); clear_expression_lookaside(); } } 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; }
/* * This is a private function to generate %set code for the * statement. At this point, the r-value is evaluated and stored in * the res vector, I just need to generate the %set statements for the * l-values of the assignment. */ static void set_vec_to_lval(ivl_statement_t net, struct vector_info res) { ivl_lval_t lval; ivl_memory_t mem; unsigned wid = res.wid; unsigned lidx; 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)); 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)); 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) { unsigned bidx = res.base < 4 ? res.base : (res.base+cur_rbit); set_to_memory(mem, idx, bidx); cur_rbit += 1; } for (idx = bit_limit; idx < ivl_lval_pins(lval); idx += 1) set_to_memory(mem, idx, 0); } else { unsigned bidx = res.base < 4 ? res.base : (res.base+cur_rbit); set_to_lvariable(lval, 0, bidx, bit_limit); cur_rbit += bit_limit; 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(); } } }