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; }
static int show_stmt_assign_sig_string(ivl_statement_t net) { 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_expr_t aidx = ivl_lval_idx(lval); ivl_signal_t var= ivl_lval_sig(lval); assert(ivl_stmt_lvals(net) == 1); assert(ivl_stmt_opcode(net) == 0); assert(ivl_lval_mux(lval) == 0); /* Simplest case: no mux. Evaluate the r-value as a string and store the result into the variable. Note that the %store/str opcode pops the string result. */ if (part == 0 && aidx == 0) { draw_eval_string(rval); fprintf(vvp_out, " %%store/str v%p_0;\n", var); return 0; } /* Assign to array. The l-value has an index expression expression so we are assigning to an array word. */ if (aidx != 0) { unsigned ix; assert(part == 0); draw_eval_string(rval); draw_eval_expr_into_integer(aidx, (ix = allocate_word())); fprintf(vvp_out, " %%store/stra v%p, %u;\n", var, ix); clr_word(ix); return 0; } /* Calculate the character select for the word. */ int mux_word = allocate_word(); draw_eval_expr_into_integer(part, mux_word); /* Evaluate the r-value as a vector. */ struct vector_info rvec = draw_eval_expr_wid(rval, 8, STUFF_OK_XZ); assert(rvec.wid == 8); fprintf(vvp_out, " %%putc/str/v v%p_0, %d, %u;\n", var, mux_word, rvec.base); clr_vector(rvec); clr_word(mux_word); return 0; }
static void function_argument_logic(ivl_signal_t port, ivl_expr_t expr) { struct vector_info res; unsigned ewidth, pwidth; /* ports cannot be arrays. */ assert(ivl_signal_dimensions(port) == 0); ewidth = ivl_expr_width(expr); pwidth = ivl_signal_width(port); /* Just like a normal assignment the function arguments need to * be evaluated at either their width or the argument width if * it is larger. */ if (ewidth < pwidth) ewidth = pwidth; res = draw_eval_expr_wid(expr, ewidth, 0); /* We could have extra bits so only select the ones we need. */ fprintf(vvp_out, " %%set/v v%p_0, %u, %u;\n", port, res.base, pwidth); clr_vector(res); }
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 show_stmt_case(ivl_statement_t net, ivl_scope_t sscope) { ivl_expr_t exp = ivl_stmt_cond_expr(net); struct vector_info cond = draw_eval_expr(exp, 0); unsigned count = ivl_stmt_case_count(net); unsigned local_base = local_count; unsigned idx, default_case; local_count += count + 1; /* First draw the branch table. All the non-default cases generate a branch out of here, to the code that implements the case. The default will fall through all the tests. */ default_case = count; for (idx = 0 ; idx < count ; idx += 1) { ivl_expr_t cex = ivl_stmt_case_expr(net, idx); struct vector_info cvec; if (cex == 0) { default_case = idx; continue; } /* Is the guard expression something I can pass to a %cmpi/u instruction? If so, use that instead. */ if ((ivl_statement_type(net) == IVL_ST_CASE) && (ivl_expr_type(cex) == IVL_EX_NUMBER) && (! number_is_unknown(cex)) && number_is_immediate(cex, 16)) { unsigned long imm = get_number_immediate(cex); fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n", cond.base, imm, cond.wid); fprintf(vvp_out, " %%jmp/1 T_%d.%d, 6;\n", thread_count, local_base+idx); continue; } /* Oh well, do this case the hard way. */ cvec = draw_eval_expr_wid(cex, cond.wid, 0); assert(cvec.wid == cond.wid); switch (ivl_statement_type(net)) { case IVL_ST_CASE: fprintf(vvp_out, " %%cmp/u %u, %u, %u;\n", cond.base, cvec.base, cond.wid); fprintf(vvp_out, " %%jmp/1 T_%d.%d, 6;\n", thread_count, local_base+idx); break; case IVL_ST_CASEX: fprintf(vvp_out, " %%cmp/x %u, %u, %u;\n", cond.base, cvec.base, cond.wid); fprintf(vvp_out, " %%jmp/1 T_%d.%d, 4;\n", thread_count, local_base+idx); break; case IVL_ST_CASEZ: fprintf(vvp_out, " %%cmp/z %u, %u, %u;\n", cond.base, cvec.base, cond.wid); fprintf(vvp_out, " %%jmp/1 T_%d.%d, 4;\n", thread_count, local_base+idx); break; default: assert(0); } /* Done with the case expression */ clr_vector(cvec); } /* Done with the condition expression */ clr_vector(cond); /* Emit code for the default case. */ if (default_case < count) { ivl_statement_t cst = ivl_stmt_case_stmt(net, default_case); show_statement(cst, sscope); } /* Jump to the out of the case. */ fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, local_base+count); for (idx = 0 ; idx < count ; idx += 1) { ivl_statement_t cst = ivl_stmt_case_stmt(net, idx); if (idx == default_case) continue; fprintf(vvp_out, "T_%d.%d ;\n", thread_count, local_base+idx); clear_expression_lookaside(); show_statement(cst, sscope); fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, local_base+count); } /* The out of the case. */ fprintf(vvp_out, "T_%d.%d ;\n", thread_count, local_base+count); clear_expression_lookaside(); return 0; }