static int show_stmt_assign_sig_darray(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_expr_t part = ivl_lval_part_off(lval); 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); ivl_expr_t mux = ivl_lval_idx(lval); assert(ivl_stmt_lvals(net) == 1); assert(ivl_stmt_opcode(net) == 0); assert(ivl_lval_mux(lval) == 0); assert(part == 0); if (mux && (ivl_type_base(element_type)==IVL_VT_REAL)) { draw_eval_real(rval); /* The %set/dar expects the array index to be in index register 3. Calculate the index in place. */ draw_eval_expr_into_integer(mux, 3); fprintf(vvp_out, " %%store/dar/r v%p_0;\n", var); } else if (mux && ivl_type_base(element_type)==IVL_VT_STRING) { /* Evaluate the rval into the top of the string stack. */ draw_eval_string(rval); /* The %store/dar/s expects the array index to me in index register 3. Calculate the index in place. */ draw_eval_expr_into_integer(mux, 3); fprintf(vvp_out, " %%store/dar/str v%p_0;\n", var); } else if (mux) { struct vector_info rvec = draw_eval_expr_wid(rval, ivl_lval_width(lval), STUFF_OK_XZ); /* The %set/dar expects the array index to be in index register 3. Calculate the index in place. */ draw_eval_expr_into_integer(mux, 3); fprintf(vvp_out, " %%set/dar v%p_0, %u, %u;\n", var, rvec.base, rvec.wid); if (rvec.base >= 4) clr_vector(rvec); } else { /* There is no l-value mux, so this must be an assignment to the array as a whole. Evaluate the "object", and store the evaluated result. */ errors += draw_eval_object(rval); fprintf(vvp_out, " %%store/obj v%p_0;\n", var); } return errors; }
/* * 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; #if 0 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); #endif 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: draw_eval_vec4(ivl_expr_parm(rval,idx)); fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx); fprintf(vvp_out, " %%store/dar/vec4 v%p_0;\n", var); 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; case IVL_VT_STRING: draw_eval_string(ivl_expr_parm(rval,idx)); fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx); fprintf(vvp_out, " %%store/dar/str 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 void show_prop_type(ivl_type_t ptype) { ivl_variable_type_t data_type = ivl_type_base(ptype); switch (data_type) { case IVL_VT_REAL: fprintf(vvp_out, "\"r\""); break; case IVL_VT_STRING: fprintf(vvp_out, "\"S\""); break; case IVL_VT_BOOL: case IVL_VT_LOGIC: show_prop_type_vector(ptype); break; case IVL_VT_DARRAY: case IVL_VT_CLASS: fprintf(vvp_out, "\"o\""); break; default: fprintf(vvp_out, "\"<ERROR-no-type>\""); assert(0); break; } }
static ivl_type_t draw_lval_expr(ivl_lval_t lval) { ivl_lval_t lval_nest = ivl_lval_nest(lval); ivl_signal_t lval_sig = ivl_lval_sig(lval); ivl_type_t sub_type; if (lval_nest) { sub_type = draw_lval_expr(lval_nest); } else { assert(lval_sig); sub_type = ivl_signal_net_type(lval_sig); assert(ivl_type_base(sub_type) == IVL_VT_CLASS); fprintf(vvp_out, " %%load/obj v%p_0;\n", lval_sig); } assert(ivl_type_base(sub_type) == IVL_VT_CLASS); if (ivl_lval_idx(lval)) { fprintf(vvp_out, " ; XXXX Don't know how to handle ivl_lval_idx values here.\n"); } fprintf(vvp_out, " %%prop/obj %d, 0; draw_lval_expr\n", ivl_lval_property_idx(lval)); fprintf(vvp_out, " %%pop/obj 1, 1;\n"); return ivl_type_prop_type(sub_type, ivl_lval_property_idx(lval)); }
static int eval_darray_new(ivl_expr_t ex) { unsigned size_reg = allocate_word(); ivl_expr_t size_expr = ivl_expr_oper1(ex); draw_eval_expr_into_integer(size_expr, size_reg); clr_word(size_reg); // The new function has a net_type that contains the details // of the type. ivl_type_t net_type = ivl_expr_net_type(ex); assert(net_type); ivl_type_t element_type = ivl_type_element(net_type); assert(element_type); switch (ivl_type_base(element_type)) { case IVL_VT_REAL: // REAL objects are not packable. assert(ivl_type_packed_dimensions(element_type) == 0); fprintf(vvp_out, " %%new/darray %u, \"r\";\n", size_reg); break; case IVL_VT_STRING: // STRING objects are not packable. assert(ivl_type_packed_dimensions(element_type) == 0); fprintf(vvp_out, " %%new/darray %u, \"S\";\n", size_reg); break; case IVL_VT_BOOL: // bool objects are vectorable, but for now only support // a single dimensions. assert(ivl_type_packed_dimensions(element_type) == 1); int msb = ivl_type_packed_msb(element_type, 0); int lsb = ivl_type_packed_lsb(element_type, 0); int wid = msb>=lsb? msb - lsb : lsb - msb; wid += 1; fprintf(vvp_out, " %%new/darray %u, \"sb%d\";\n", size_reg, wid); break; default: assert(0); break; } return 0; }
void show_net_type(ivl_type_t net_type) { ivl_variable_type_t data_type = ivl_type_base(net_type); switch (data_type) { case IVL_VT_NO_TYPE: fprintf(out, "<ERROR-no-type>"); stub_errors += 1; break; case IVL_VT_BOOL: fprintf(out, "bool"); break; case IVL_VT_LOGIC: fprintf(out, "logic"); break; case IVL_VT_REAL: fprintf(out, "real"); break; case IVL_VT_STRING: fprintf(out, "string"); break; case IVL_VT_DARRAY: show_net_type_darray(net_type); break; case IVL_VT_CLASS: fprintf(out, "class"); break; case IVL_VT_QUEUE: show_net_type_queue(net_type); break; case IVL_VT_VOID: fprintf(out, "void"); break; } unsigned packed_dimensions = ivl_type_packed_dimensions(net_type); unsigned idx; for (idx = 0 ; idx < packed_dimensions ; idx += 1) { fprintf(out, "[%d:%d]", ivl_type_packed_msb(net_type, idx), ivl_type_packed_lsb(net_type, idx)); } }
static void show_prop_type_vector(ivl_type_t ptype) { ivl_variable_type_t data_type = ivl_type_base(ptype); unsigned packed_dimensions = ivl_type_packed_dimensions(ptype); assert(packed_dimensions < 2); const char*signed_flag = ivl_type_signed(ptype)? "s" : ""; char code = data_type==IVL_VT_BOOL? 'b' : 'L'; if (packed_dimensions == 0) { fprintf(vvp_out, "\"%s%c1\"", signed_flag, code); } else { assert(packed_dimensions == 1); assert(ivl_type_packed_lsb(ptype,0) == 0); assert(ivl_type_packed_msb(ptype,0) >= 0); fprintf(vvp_out, "\"%s%c%d\"", signed_flag, code, ivl_type_packed_msb(ptype,0)+1); } }
static int show_stmt_assign_sig_queue(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_QUEUE); switch (ivl_expr_type(rval)) { case IVL_EX_NULL: errors += draw_eval_object(rval); break; default: fprintf(stderr, "XXXX: I don't know how to handle expr_type=%d here\n", ivl_expr_type(rval)); fprintf(vvp_out, " ; XXXX expr_type=%d\n", ivl_expr_type(rval)); errors += 1; break; } fprintf(vvp_out, " %%store/obj v%p_0;\n", var); return errors; }
static int show_stmt_assign_sig_cobject(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 sig= ivl_lval_sig(lval); int prop_idx = ivl_lval_property_idx(lval); if (prop_idx >= 0) { ivl_type_t sig_type = ivl_signal_net_type(sig); ivl_type_t prop_type = ivl_type_prop_type(sig_type, prop_idx); if (ivl_type_base(prop_type) == IVL_VT_BOOL) { assert(ivl_type_packed_dimensions(prop_type) == 1); assert(ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)); int wid = ivl_type_packed_msb(prop_type,0) - ivl_type_packed_lsb(prop_type,0) + 1; struct vector_info val = draw_eval_expr_wid(rval, wid, STUFF_OK_XZ); fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); fprintf(vvp_out, " %%store/prop/v %d, %u, %u; Store in bool property %s\n", prop_idx, val.base, val.wid, ivl_type_prop_name(sig_type, prop_idx)); fprintf(vvp_out, " %%pop/obj 1;\n"); clr_vector(val); } else if (ivl_type_base(prop_type) == IVL_VT_LOGIC) { assert(ivl_type_packed_dimensions(prop_type) == 1); assert(ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)); int wid = ivl_type_packed_msb(prop_type,0) - ivl_type_packed_lsb(prop_type,0) + 1; struct vector_info val = draw_eval_expr_wid(rval, wid, STUFF_OK_XZ); fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); fprintf(vvp_out, " %%store/prop/v %d, %u, %u; Store in logic property %s\n", prop_idx, val.base, val.wid, ivl_type_prop_name(sig_type, prop_idx)); fprintf(vvp_out, " %%pop/obj 1;\n"); clr_vector(val); } else if (ivl_type_base(prop_type) == IVL_VT_REAL) { /* Calculate the real value into the real value stack. The %store/prop/r will pop the stack value. */ draw_eval_real(rval); fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); fprintf(vvp_out, " %%store/prop/r %d;\n", prop_idx); fprintf(vvp_out, " %%pop/obj 1;\n"); } else if (ivl_type_base(prop_type) == IVL_VT_STRING) { /* Calculate the string value into the string value stack. The %store/prop/r will pop the stack value. */ draw_eval_string(rval); fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); fprintf(vvp_out, " %%store/prop/str %d;\n", prop_idx); fprintf(vvp_out, " %%pop/obj 1;\n"); } else if (ivl_type_base(prop_type) == IVL_VT_DARRAY) { /* The property is a darray, and there is no mux expression to the assignment is of an entire array object. */ fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); draw_eval_object(rval); fprintf(vvp_out, " %%store/prop/obj %d;\n", prop_idx); fprintf(vvp_out, " %%pop/obj 1;\n"); } else if (ivl_type_base(prop_type) == IVL_VT_CLASS) { /* The property is a class object. */ fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); draw_eval_object(rval); fprintf(vvp_out, " %%store/prop/obj %d;\n", prop_idx); fprintf(vvp_out, " %%pop/obj 1;\n"); } else { fprintf(vvp_out, " ; ERROR: ivl_type_base(prop_type) = %d\n", ivl_type_base(prop_type)); assert(0); } } else { /* There is no property select, so evaluate the r-value as an object and assign the entire object to the variable. */ errors += draw_eval_object(rval); fprintf(vvp_out, " %%store/obj v%p_0;\n", sig); } return errors; }
static int eval_darray_new(ivl_expr_t ex) { int errors = 0; unsigned size_reg = allocate_word(); ivl_expr_t size_expr = ivl_expr_oper1(ex); ivl_expr_t init_expr = ivl_expr_oper2(ex); draw_eval_expr_into_integer(size_expr, size_reg); // The new function has a net_type that contains the details // of the type. ivl_type_t net_type = ivl_expr_net_type(ex); assert(net_type); ivl_type_t element_type = ivl_type_element(net_type); assert(element_type); switch (ivl_type_base(element_type)) { int msb, lsb, wid; case IVL_VT_REAL: // REAL objects are not packable. assert(ivl_type_packed_dimensions(element_type) == 0); fprintf(vvp_out, " %%new/darray %u, \"r\";\n", size_reg); break; case IVL_VT_STRING: // STRING objects are not packable. assert(ivl_type_packed_dimensions(element_type) == 0); fprintf(vvp_out, " %%new/darray %u, \"S\";\n", size_reg); break; case IVL_VT_BOOL: // bool objects are vectorable, but for now only support // a single dimensions. assert(ivl_type_packed_dimensions(element_type) == 1); msb = ivl_type_packed_msb(element_type, 0); lsb = ivl_type_packed_lsb(element_type, 0); wid = msb>=lsb? msb - lsb : lsb - msb; wid += 1; fprintf(vvp_out, " %%new/darray %u, \"%sb%d\";\n", size_reg, ivl_type_signed(element_type) ? "s" : "", wid); break; case IVL_VT_LOGIC: // logic objects are vectorable, but for now only support // a single dimensions. assert(ivl_type_packed_dimensions(element_type) == 1); msb = ivl_type_packed_msb(element_type, 0); lsb = ivl_type_packed_lsb(element_type, 0); wid = msb>=lsb? msb - lsb : lsb - msb; wid += 1; fprintf(vvp_out, " %%new/darray %u, \"%sv%d\";\n", size_reg, ivl_type_signed(element_type) ? "s" : "", wid); break; default: assert(0); break; } clr_word(size_reg); if (init_expr && ivl_expr_type(init_expr)==IVL_EX_ARRAY_PATTERN) { unsigned idx; switch (ivl_type_base(element_type)) { case IVL_VT_BOOL: case IVL_VT_LOGIC: for (idx = 0 ; idx < ivl_expr_parms(init_expr) ; idx += 1) { draw_eval_vec4(ivl_expr_parm(init_expr,idx)); fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx); fprintf(vvp_out, " %%set/dar/obj/vec4 3;\n"); fprintf(vvp_out, " %%pop/vec4 1;\n"); } break; case IVL_VT_REAL: for (idx = 0 ; idx < ivl_expr_parms(init_expr) ; idx += 1) { draw_eval_real(ivl_expr_parm(init_expr,idx)); fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx); fprintf(vvp_out, " %%set/dar/obj/real 3;\n"); fprintf(vvp_out, " %%pop/real 1;\n"); } break; case IVL_VT_STRING: for (idx = 0 ; idx < ivl_expr_parms(init_expr) ; idx += 1) { draw_eval_string(ivl_expr_parm(init_expr,idx)); fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx); fprintf(vvp_out, " %%set/dar/obj/str 3;\n"); fprintf(vvp_out, " %%pop/str 1;\n"); } break; default: fprintf(vvp_out, "; ERROR: Sorry, this type not supported here.\n"); errors += 1; break; } } else if (init_expr && (ivl_expr_value(init_expr) == IVL_VT_DARRAY)) { ivl_signal_t sig = ivl_expr_signal(init_expr); fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); fprintf(vvp_out, " %%scopy;\n"); } else if (init_expr && number_is_immediate(size_expr,32,0)) { /* In this case, there is an init expression, the expression is NOT an array_pattern, and the size expression used to calculate the size of the array is a constant. Generate an unrolled set of assignments. */ long idx; long cnt = get_number_immediate(size_expr); unsigned wid; switch (ivl_type_base(element_type)) { case IVL_VT_BOOL: case IVL_VT_LOGIC: wid = width_of_packed_type(element_type); for (idx = 0 ; idx < cnt ; idx += 1) { draw_eval_vec4(init_expr); fprintf(vvp_out, " %%parti/%c %u, %ld, 6;\n", ivl_expr_signed(init_expr) ? 's' : 'u', wid, idx * wid); fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", cnt - idx - 1); fprintf(vvp_out, " %%set/dar/obj/vec4 3;\n"); fprintf(vvp_out, " %%pop/vec4 1;\n"); } break; case IVL_VT_REAL: draw_eval_real(init_expr); for (idx = 0 ; idx < cnt ; idx += 1) { fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", idx); fprintf(vvp_out, " %%set/dar/obj/real 3;\n"); } fprintf(vvp_out, " %%pop/real 1;\n"); break; case IVL_VT_STRING: draw_eval_string(init_expr); for (idx = 0 ; idx < cnt ; idx += 1) { fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", idx); fprintf(vvp_out, " %%set/dar/obj/str 3;\n"); } fprintf(vvp_out, " %%pop/str 1;\n"); break; default: fprintf(vvp_out, "; ERROR: Sorry, this type not supported here.\n"); errors += 1; break; } } else if (init_expr) { fprintf(vvp_out, "; ERROR: Sorry, I don't know how to work with this size expr.\n"); errors += 1; } return errors; }
static int show_stmt_assign_sig_cobject(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 sig= ivl_lval_sig(lval); unsigned lwid = ivl_lval_width(lval); int prop_idx = ivl_lval_property_idx(lval); if (prop_idx >= 0) { ivl_type_t sig_type = ivl_signal_net_type(sig); ivl_type_t prop_type = ivl_type_prop_type(sig_type, prop_idx); if (ivl_type_base(prop_type) == IVL_VT_BOOL) { assert(ivl_type_packed_dimensions(prop_type) == 1); assert(ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)); draw_eval_vec4(rval); if (ivl_expr_value(rval)!=IVL_VT_BOOL) fprintf(vvp_out, " %%cast2;\n"); fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); fprintf(vvp_out, " %%store/prop/v %d, %u; Store in bool property %s\n", prop_idx, lwid, ivl_type_prop_name(sig_type, prop_idx)); fprintf(vvp_out, " %%pop/obj 1, 0;\n"); } else if (ivl_type_base(prop_type) == IVL_VT_LOGIC) { assert(ivl_type_packed_dimensions(prop_type) == 1); assert(ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)); draw_eval_vec4(rval); fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); fprintf(vvp_out, " %%store/prop/v %d, %u; Store in logic property %s\n", prop_idx, lwid, ivl_type_prop_name(sig_type, prop_idx)); fprintf(vvp_out, " %%pop/obj 1, 0;\n"); } else if (ivl_type_base(prop_type) == IVL_VT_REAL) { /* Calculate the real value into the real value stack. The %store/prop/r will pop the stack value. */ draw_eval_real(rval); fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); fprintf(vvp_out, " %%store/prop/r %d;\n", prop_idx); fprintf(vvp_out, " %%pop/obj 1, 0;\n"); } else if (ivl_type_base(prop_type) == IVL_VT_STRING) { /* Calculate the string value into the string value stack. The %store/prop/r will pop the stack value. */ draw_eval_string(rval); fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); fprintf(vvp_out, " %%store/prop/str %d;\n", prop_idx); fprintf(vvp_out, " %%pop/obj 1, 0;\n"); } else if (ivl_type_base(prop_type) == IVL_VT_DARRAY) { int idx = 0; /* The property is a darray, and there is no mux expression to the assignment is of an entire array object. */ fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); draw_eval_object(rval); fprintf(vvp_out, " %%store/prop/obj %d, %d; IVL_VT_DARRAY\n", prop_idx, idx); fprintf(vvp_out, " %%pop/obj 1, 0;\n"); } else if (ivl_type_base(prop_type) == IVL_VT_CLASS) { int idx = 0; ivl_expr_t idx_expr; if ( (idx_expr = ivl_lval_idx(lval)) ) { idx = allocate_word(); } /* The property is a class object. */ fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); draw_eval_object(rval); if (idx_expr) draw_eval_expr_into_integer(idx_expr, idx); fprintf(vvp_out, " %%store/prop/obj %d, %d; IVL_VT_CLASS\n", prop_idx, idx); fprintf(vvp_out, " %%pop/obj 1, 0;\n"); if (idx_expr) clr_word(idx); } else { fprintf(vvp_out, " ; ERROR: ivl_type_base(prop_type) = %d\n", ivl_type_base(prop_type)); assert(0); } } else { /* There is no property select, so evaluate the r-value as an object and assign the entire object to the variable. */ errors += draw_eval_object(rval); if (ivl_signal_array_count(sig) > 1) { unsigned ix; ivl_expr_t aidx = ivl_lval_idx(lval); draw_eval_expr_into_integer(aidx, (ix = allocate_word())); fprintf(vvp_out, " %%store/obja v%p, %u;\n", sig, ix); clr_word(ix); } else { /* Not an array, so no index expression */ fprintf(vvp_out, " %%store/obj v%p_0;\n", sig); } } return errors; }
static int show_stmt_assign_sig_darray(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_expr_t part = ivl_lval_part_off(lval); 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); ivl_expr_t mux = ivl_lval_idx(lval); assert(ivl_stmt_lvals(net) == 1); assert(ivl_stmt_opcode(net) == 0); assert(part == 0); if (mux && (ivl_type_base(element_type)==IVL_VT_REAL)) { draw_eval_real(rval); /* The %set/dar expects the array index to be in index register 3. Calculate the index in place. */ draw_eval_expr_into_integer(mux, 3); fprintf(vvp_out, " %%store/dar/r v%p_0;\n", var); } else if (mux && ivl_type_base(element_type)==IVL_VT_STRING) { /* Evaluate the rval into the top of the string stack. */ draw_eval_string(rval); /* The %store/dar/s expects the array index to me in index register 3. Calculate the index in place. */ draw_eval_expr_into_integer(mux, 3); fprintf(vvp_out, " %%store/dar/str v%p_0;\n", var); } else if (mux) { draw_eval_vec4(rval); /* The %store/dar/vec4 expects the array index to be in index register 3. Calculate the index in place. */ draw_eval_expr_into_integer(mux, 3); fprintf(vvp_out, " %%store/dar/vec4 v%p_0;\n", var); } 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 "object", and store the evaluated result. */ errors += draw_eval_object(rval); fprintf(vvp_out, " %%store/obj v%p_0;\n", var); } return errors; }
/* * Store a vector from the vec4 stack to the statement l-values. This * all assumes that the value to be assigned is already on the top of * the stack. * * NOTE TO SELF: The %store/vec4 takes a width, but the %assign/vec4 * instructions do not, instead relying on the expression width. I * think that it the proper way to do it, so soon I should change the * %store/vec4 to not include the width operand. */ static void store_vec4_to_lval(ivl_statement_t net) { for (unsigned lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) { ivl_lval_t lval = ivl_stmt_lval(net,lidx); ivl_signal_t lsig = ivl_lval_sig(lval); ivl_lval_t nest = ivl_lval_nest(lval); unsigned lwid = ivl_lval_width(lval); ivl_expr_t part_off_ex = ivl_lval_part_off(lval); /* This is non-nil if the l-val is the word of a memory, and nil otherwise. */ ivl_expr_t word_ex = ivl_lval_idx(lval); if (lidx+1 < ivl_stmt_lvals(net)) fprintf(vvp_out, " %%split/vec4 %u;\n", lwid); if (word_ex) { /* Handle index into an array */ int word_index = allocate_word(); int part_index = 0; /* Calculate the word address into word_index */ draw_eval_expr_into_integer(word_ex, word_index); /* If there is a part_offset, calculate it into part_index. */ if (part_off_ex) { int flag_index = allocate_flag(); part_index = allocate_word(); fprintf(vvp_out, " %%flag_mov %d, 4;\n", flag_index); draw_eval_expr_into_integer(part_off_ex, part_index); fprintf(vvp_out, " %%flag_or 4, %d;\n", flag_index); clr_flag(flag_index); } assert(lsig); fprintf(vvp_out, " %%store/vec4a v%p, %d, %d;\n", lsig, word_index, part_index); clr_word(word_index); if (part_index) clr_word(part_index); } else if (part_off_ex) { /* Dynamically calculated part offset */ int offset_index = allocate_word(); draw_eval_expr_into_integer(part_off_ex, offset_index); /* Note that flag4 is set by the eval above. */ assert(lsig); if (ivl_signal_type(lsig)==IVL_SIT_UWIRE) { fprintf(vvp_out, " %%force/vec4/off v%p_0, %u;\n", lsig, offset_index); } else { fprintf(vvp_out, " %%store/vec4 v%p_0, %d, %u;\n", lsig, offset_index, lwid); } clr_word(offset_index); } else if (nest) { /* No offset expression, but the l-value is nested, which probably means that it is a class member. We will use a property assign function. */ assert(!lsig); ivl_type_t sub_type = draw_lval_expr(nest); assert(ivl_type_base(sub_type) == IVL_VT_CLASS); fprintf(vvp_out, " %%store/prop/v %u, %u;\n", ivl_lval_property_idx(lval), lwid); fprintf(vvp_out, " %%pop/obj 1, 0;\n"); } else { /* No offset expression, so use simpler store function. */ assert(lsig); assert(lwid == ivl_signal_width(lsig)); fprintf(vvp_out, " %%store/vec4 v%p_0, 0, %u;\n", lsig, lwid); } } }