diff --git a/ivtest/ivltests/sv_class_prop_assign_op1.v b/ivtest/ivltests/sv_class_prop_assign_op1.v new file mode 100644 index 000000000..7d000d7fd --- /dev/null +++ b/ivtest/ivltests/sv_class_prop_assign_op1.v @@ -0,0 +1,58 @@ +// Check that assignment operators are supported on class properties. + +module test; + + bit failed = 1'b0; + + `define check(val, exp) do \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end \ + while(0) + + class C; + integer x; + endclass + + integer i; + C c; + + initial begin + c = new; + + c.x = 1; + c.x += 5; + `check(c.x, 6); + c.x -= 2; + `check(c.x, 4); + c.x *= 25; + `check(c.x, 100); + c.x /= 5; + `check(c.x, 20); + c.x %= 3; + `check(c.x, 2); + + c.x = 'haa; + c.x &= 'h33; + `check(c.x, 'h22); + c.x |= 'h11; + `check(c.x, 'h33); + c.x ^= 'h22; + `check(c.x, 'h11); + + c.x <<= 3; + `check(c.x, 'h88); + c.x <<<= 1; + `check(c.x, 'h110); + c.x >>= 2; + `check(c.x, 'h44); + c.x >>>= 1; + `check(c.x, 'h22); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_class_prop_assign_op2.v b/ivtest/ivltests/sv_class_prop_assign_op2.v new file mode 100644 index 000000000..a590c45f0 --- /dev/null +++ b/ivtest/ivltests/sv_class_prop_assign_op2.v @@ -0,0 +1,58 @@ +// Check that assignment operators are supported on static class properties. + +module test; + + bit failed = 1'b0; + + `define check(val, exp) do \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end \ + while(0) + + class C; + static integer x; + endclass + + integer i; + C c; + + initial begin + c = new; + + c.x = 1; + c.x += 5; + `check(c.x, 6); + c.x -= 2; + `check(c.x, 4); + c.x *= 25; + `check(c.x, 100); + c.x /= 5; + `check(c.x, 20); + c.x %= 3; + `check(c.x, 2); + + c.x = 'haa; + c.x &= 'h33; + `check(c.x, 'h22); + c.x |= 'h11; + `check(c.x, 'h33); + c.x ^= 'h22; + `check(c.x, 'h11); + + c.x <<= 3; + `check(c.x, 'h88); + c.x <<<= 1; + `check(c.x, 'h110); + c.x >>= 2; + `check(c.x, 'h44); + c.x >>>= 1; + `check(c.x, 'h22); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_darray_assign_op.v b/ivtest/ivltests/sv_darray_assign_op.v new file mode 100644 index 000000000..c57818932 --- /dev/null +++ b/ivtest/ivltests/sv_darray_assign_op.v @@ -0,0 +1,86 @@ +// Check that assignment operators are supported on dynamic array elements. + +module test; + + bit failed = 1'b0; + + `define check(val, exp) do \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end \ + while(0) + + integer x[]; + integer i; + + initial begin + x = new[2]; + + // Static index + x[1] = 1; + x[1] += 5; + `check(x[1], 6); + x[1] -= 2; + `check(x[1], 4); + x[1] *= 25; + `check(x[1], 100); + x[1] /= 5; + `check(x[1], 20); + x[1] %= 3; + `check(x[1], 2); + + x[1] = 'haa; + x[1] &= 'h33; + `check(x[1], 'h22); + x[1] |= 'h11; + `check(x[1], 'h33); + x[1] ^= 'h22; + `check(x[1], 'h11); + + x[1] <<= 3; + `check(x[1], 'h88); + x[1] <<<= 1; + `check(x[1], 'h110); + x[1] >>= 2; + `check(x[1], 'h44); + x[1] >>>= 1; + `check(x[1], 'h22); + + // Dynamic index + x[1] = 1; + i = 1; + x[i] += 5; + `check(x[i], 6); + x[i] -= 2; + `check(x[i], 4); + x[i] *= 25; + `check(x[i], 100); + x[i] /= 5; + `check(x[i], 20); + x[i] %= 3; + `check(x[i], 2); + + x[i] = 'haa; + x[i] &= 'h33; + `check(x[i], 'h22); + x[i] |= 'h11; + `check(x[i], 'h33); + x[i] ^= 'h22; + `check(x[i], 'h11); + + x[i] <<= 3; + `check(x[i], 'h88); + x[i] <<<= 1; + `check(x[i], 'h110); + x[i] >>= 2; + `check(x[i], 'h44); + x[i] >>>= 1; + `check(x[i], 'h22); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_queue_assign_op.v b/ivtest/ivltests/sv_queue_assign_op.v new file mode 100644 index 000000000..c97e9c980 --- /dev/null +++ b/ivtest/ivltests/sv_queue_assign_op.v @@ -0,0 +1,84 @@ +// Check that assignment operators are supported on queue elements. + +module test; + + bit failed = 1'b0; + + `define check(val, exp) do \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end \ + while(0) + + integer x[$]; + integer i; + + initial begin + x = '{0, 1}; + // Static index + x[1] += 5; + `check(x[1], 6); + x[1] -= 2; + `check(x[1], 4); + x[1] *= 25; + `check(x[1], 100); + x[1] /= 5; + `check(x[1], 20); + x[1] %= 3; + `check(x[1], 2); + + x[1] = 'haa; + x[1] &= 'h33; + `check(x[1], 'h22); + x[1] |= 'h11; + `check(x[1], 'h33); + x[1] ^= 'h22; + `check(x[1], 'h11); + + x[1] <<= 3; + `check(x[1], 'h88); + x[1] <<<= 1; + `check(x[1], 'h110); + x[1] >>= 2; + `check(x[1], 'h44); + x[1] >>>= 1; + `check(x[1], 'h22); + + // Dynamic index + x[1] = 1; + i = 1; + x[i] += 5; + `check(x[i], 6); + x[i] -= 2; + `check(x[i], 4); + x[i] *= 25; + `check(x[i], 100); + x[i] /= 5; + `check(x[i], 20); + x[i] %= 3; + `check(x[i], 2); + + x[i] = 'haa; + x[i] &= 'h33; + `check(x[i], 'h22); + x[i] |= 'h11; + `check(x[i], 'h33); + x[i] ^= 'h22; + `check(x[i], 'h11); + + x[i] <<= 3; + `check(x[i], 'h88); + x[i] <<<= 1; + `check(x[i], 'h110); + x[i] >>= 2; + `check(x[i], 'h44); + x[i] >>>= 1; + `check(x[i], 'h22); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index 6c05287de..dcba81515 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -222,6 +222,8 @@ sv_chained_constructor2 vvp_tests/sv_chained_constructor2.json sv_chained_constructor3 vvp_tests/sv_chained_constructor3.json sv_chained_constructor4 vvp_tests/sv_chained_constructor4.json sv_chained_constructor5 vvp_tests/sv_chained_constructor5.json +sv_class_prop_assign_op1 vvp_tests/sv_class_prop_assign_op1.json +sv_class_prop_assign_op2 vvp_tests/sv_class_prop_assign_op2.json sv_class_prop_logic vvp_tests/sv_class_prop_logic.json sv_const1 vvp_tests/sv_const1.json sv_const2 vvp_tests/sv_const2.json @@ -237,6 +239,7 @@ sv_const_fail6 vvp_tests/sv_const_fail6.json sv_const_fail7 vvp_tests/sv_const_fail7.json sv_const_fail8 vvp_tests/sv_const_fail8.json sv_const_fail9 vvp_tests/sv_const_fail9.json +sv_darray_assign_op vvp_tests/sv_darray_assign_op.json sv_default_port_value1 vvp_tests/sv_default_port_value1.json sv_default_port_value2 vvp_tests/sv_default_port_value2.json sv_default_port_value3 vvp_tests/sv_default_port_value3.json @@ -255,6 +258,7 @@ sv_module_port2 vvp_tests/sv_module_port2.json sv_module_port3 vvp_tests/sv_module_port3.json sv_module_port4 vvp_tests/sv_module_port4.json sv_parameter_type vvp_tests/sv_parameter_type.json +sv_queue_assign_op vvp_tests/sv_queue_assign_op.json sv_wildcard_import8 vvp_tests/sv_wildcard_import8.json sdf_header vvp_tests/sdf_header.json task_return1 vvp_tests/task_return1.json diff --git a/ivtest/vvp_tests/sv_class_prop_assign_op1.json b/ivtest/vvp_tests/sv_class_prop_assign_op1.json new file mode 100644 index 000000000..ce63aecf4 --- /dev/null +++ b/ivtest/vvp_tests/sv_class_prop_assign_op1.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_class_prop_assign_op1.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_class_prop_assign_op2.json b/ivtest/vvp_tests/sv_class_prop_assign_op2.json new file mode 100644 index 000000000..9079785f9 --- /dev/null +++ b/ivtest/vvp_tests/sv_class_prop_assign_op2.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_class_prop_assign_op2.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_darray_assign_op.json b/ivtest/vvp_tests/sv_darray_assign_op.json new file mode 100644 index 000000000..065ed73fa --- /dev/null +++ b/ivtest/vvp_tests/sv_darray_assign_op.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_darray_assign_op.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_queue_assign_op.json b/ivtest/vvp_tests/sv_queue_assign_op.json new file mode 100644 index 000000000..b4c2136ec --- /dev/null +++ b/ivtest/vvp_tests/sv_queue_assign_op.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_queue_assign_op.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 8c007ac07..94aed6242 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -541,13 +541,77 @@ static unsigned int draw_array_pattern(ivl_signal_t var, ivl_expr_t rval, return array_idx; } +static void draw_stmt_assign_vector_opcode(unsigned char opcode, bool is_signed) +{ + int idx_reg; + + switch (opcode) { + case 0: + break; + + case '+': + fprintf(vvp_out, " %%add;\n"); + break; + + case '-': + fprintf(vvp_out, " %%sub;\n"); + break; + + case '*': + fprintf(vvp_out, " %%mul;\n"); + break; + + case '/': + fprintf(vvp_out, " %%div%s;\n", is_signed ? "/s":""); + break; + + case '%': + fprintf(vvp_out, " %%mod%s;\n", is_signed ? "/s":""); + break; + + case '&': + fprintf(vvp_out, " %%and;\n"); + break; + + case '|': + fprintf(vvp_out, " %%or;\n"); + break; + + case '^': + fprintf(vvp_out, " %%xor;\n"); + break; + + case 'l': /* lval <<= expr */ + idx_reg = allocate_word(); + fprintf(vvp_out, " %%ix/vec4 %d;\n", idx_reg); + fprintf(vvp_out, " %%shiftl %d;\n", idx_reg); + clr_word(idx_reg); + break; + + case 'r': /* lval >>= expr */ + idx_reg = allocate_word(); + fprintf(vvp_out, " %%ix/vec4 %d;\n", idx_reg); + fprintf(vvp_out, " %%shiftr %d;\n", idx_reg); + clr_word(idx_reg); + break; + + case 'R': /* lval >>>= expr */ + idx_reg = allocate_word(); + fprintf(vvp_out, " %%ix/vec4 %d;\n", idx_reg); + fprintf(vvp_out, " %%shiftr/s %d;\n", idx_reg); + clr_word(idx_reg); + break; + + default: + fprintf(vvp_out, "; UNSUPPORTED ASSIGNMENT OPCODE: %c\n", opcode); + assert(0); + break; + } +} + 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; - int idx_reg; if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) { ivl_lval_t lval = ivl_stmt_lval(net, 0); @@ -556,96 +620,30 @@ static int show_stmt_assign_vector(ivl_statement_t net) return 0; } + unsigned wid = ivl_stmt_lwidth(net); + /* 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) { + struct vec_slice_info *slices; + + slices = calloc(ivl_stmt_lvals(net), sizeof(struct vec_slice_info)); + fprintf(vvp_out, " ; show_stmt_assign_vector: Get l-value for compressed %c= operand\n", ivl_stmt_opcode(net)); - slices = calloc(ivl_stmt_lvals(net), sizeof(struct vec_slice_info)); get_vec_from_lval(net, slices); - } - - unsigned wid = ivl_stmt_lwidth(net); - draw_eval_vec4(rval); - resize_vec4_wid(rval, wid); - - switch (ivl_stmt_opcode(net)) { - case 0: + draw_eval_vec4(rval); + resize_vec4_wid(rval, wid); + draw_stmt_assign_vector_opcode(ivl_stmt_opcode(net), + ivl_expr_signed(rval)); + put_vec_to_lval(net, slices); + free(slices); + } else { + draw_eval_vec4(rval); + resize_vec4_wid(rval, wid); store_vec4_to_lval(net); - break; - - case '+': - fprintf(vvp_out, " %%add;\n"); - put_vec_to_lval(net, slices); - break; - - case '-': - fprintf(vvp_out, " %%sub;\n"); - put_vec_to_lval(net, slices); - break; - - case '*': - fprintf(vvp_out, " %%mul;\n"); - put_vec_to_lval(net, slices); - break; - - case '/': - fprintf(vvp_out, " %%div%s;\n", ivl_expr_signed(rval)? "/s":""); - put_vec_to_lval(net, slices); - break; - - case '%': - fprintf(vvp_out, " %%mod%s;\n", ivl_expr_signed(rval)? "/s":""); - put_vec_to_lval(net, slices); - break; - - case '&': - fprintf(vvp_out, " %%and;\n"); - put_vec_to_lval(net, slices); - break; - - case '|': - fprintf(vvp_out, " %%or;\n"); - put_vec_to_lval(net, slices); - break; - - case '^': - fprintf(vvp_out, " %%xor;\n"); - put_vec_to_lval(net, slices); - break; - - case 'l': /* lval <<= expr */ - idx_reg = allocate_word(); - fprintf(vvp_out, " %%ix/vec4 %d;\n", idx_reg); - fprintf(vvp_out, " %%shiftl %d;\n", idx_reg); - clr_word(idx_reg); - put_vec_to_lval(net, slices); - break; - - case 'r': /* lval >>= expr */ - idx_reg = allocate_word(); - fprintf(vvp_out, " %%ix/vec4 %d;\n", idx_reg); - fprintf(vvp_out, " %%shiftr %d;\n", idx_reg); - clr_word(idx_reg); - put_vec_to_lval(net, slices); - break; - - case 'R': /* lval >>>= expr */ - idx_reg = allocate_word(); - fprintf(vvp_out, " %%ix/vec4 %d;\n", idx_reg); - fprintf(vvp_out, " %%shiftr/s %d;\n", idx_reg); - clr_word(idx_reg); - put_vec_to_lval(net, slices); - break; - - default: - fprintf(vvp_out, "; UNSUPPORTED ASSIGNMENT OPCODE: %c\n", ivl_stmt_opcode(net)); - assert(0); - break; } - if (slices) free(slices); - return 0; } @@ -817,42 +815,11 @@ static void store_real_to_lval(ivl_lval_t lval) clr_word(word_ix); } -/* - * This function assigns a value to a real variable. This is destined - * for /dev/null when typed ivl_signal_t takes over all the real - * variable support. - */ -static int show_stmt_assign_sig_real(ivl_statement_t net) +static void draw_stmt_assign_real_opcode(unsigned char opcode) { - struct real_lval_info*slice = 0; - ivl_lval_t lval; - - assert(ivl_stmt_lvals(net) == 1); - lval = ivl_stmt_lval(net, 0); - - ivl_expr_t rval = ivl_stmt_rval(net); - if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) { - ivl_signal_t sig = ivl_lval_sig(lval); - draw_array_pattern(sig, rval, 0); - return 0; - } - - /* If this is a compressed assignment, then get the contents - of the l-value. We need this value as part of the r-value - calculation. */ - if (ivl_stmt_opcode(net) != 0) { - fprintf(vvp_out, " ; show_stmt_assign_real: Get l-value for compressed %c= operand\n", ivl_stmt_opcode(net)); - slice = calloc(1, sizeof(struct real_lval_info)); - get_real_from_lval(lval, slice); - } - - draw_eval_real(rval); - - switch (ivl_stmt_opcode(net)) { + switch (opcode) { case 0: - store_real_to_lval(lval); - if (slice) free(slice); - return 0; + break; case '+': fprintf(vvp_out, " %%add/wr;\n"); @@ -875,13 +842,47 @@ static int show_stmt_assign_sig_real(ivl_statement_t net) break; default: - fprintf(vvp_out, "; UNSUPPORTED ASSIGNMENT OPCODE: %c\n", ivl_stmt_opcode(net)); + fprintf(vvp_out, "; UNSUPPORTED ASSIGNMENT OPCODE: %c\n", opcode); assert(0); break; } +} + +/* + * This function assigns a value to a real variable. This is destined + * for /dev/null when typed ivl_signal_t takes over all the real + * variable support. + */ +static int show_stmt_assign_sig_real(ivl_statement_t net) +{ + ivl_lval_t lval; + + assert(ivl_stmt_lvals(net) == 1); + lval = ivl_stmt_lval(net, 0); + + ivl_expr_t rval = ivl_stmt_rval(net); + if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) { + ivl_signal_t sig = ivl_lval_sig(lval); + draw_array_pattern(sig, rval, 0); + return 0; + } + + /* If this is a compressed assignment, then get the contents + of the l-value. We need this value as part of the r-value + calculation. */ + if (ivl_stmt_opcode(net) != 0) { + struct real_lval_info slice; + + fprintf(vvp_out, " ; show_stmt_assign_real: Get l-value for compressed %c= operand\n", ivl_stmt_opcode(net)); + get_real_from_lval(lval, &slice); + draw_eval_real(rval); + draw_stmt_assign_real_opcode(ivl_stmt_opcode(net)); + put_real_to_lval(lval, &slice); + } else { + draw_eval_real(rval); + store_real_to_lval(lval); + } - put_real_to_lval(lval, slice); - free(slice); return 0; } @@ -1019,6 +1020,84 @@ static int show_stmt_assign_darray_pattern(ivl_statement_t net) return errors; } +/* + * Loading an element and updating it is identical for queues and dynamic arrays + * and is handled here. The updated value is left on the stack and will be + * written back using type specific functions. + */ +static void show_stmt_assign_sig_darray_queue_mux(ivl_statement_t net) +{ + ivl_lval_t lval = ivl_stmt_lval(net, 0); + ivl_signal_t var = ivl_lval_sig(lval); + ivl_type_t var_type = ivl_signal_net_type(var); + ivl_type_t element_type = ivl_type_element(var_type); + ivl_expr_t mux = ivl_lval_idx(lval); + ivl_expr_t rval = ivl_stmt_rval(net); + + /* + * Queue and dynamic array load and store functions expect the element + * address in index register 3. The index expression must only be + * evaluated once. So in case of an assignment operator it is moved to a + * scratch register and restored to the index register once the rvalue has + * been evaluated. + */ + + switch (ivl_type_base(element_type)) { + case IVL_VT_REAL: + if (ivl_stmt_opcode(net) != 0) { + int mux_word = allocate_word(); + int flag = allocate_flag(); + + draw_eval_expr_into_integer(mux, 3); + fprintf(vvp_out, " %%ix/mov %d, 3;\n", mux_word); + fprintf(vvp_out, " %%flag_mov %u, 4;\n", flag); + fprintf(vvp_out, " %%load/dar/r v%p_0;\n", var); + draw_eval_real(rval); + draw_stmt_assign_real_opcode(ivl_stmt_opcode(net)); + fprintf(vvp_out, " %%flag_mov 4, %d;\n", flag); + fprintf(vvp_out, " %%ix/mov 3, %d;\n", mux_word); + clr_flag(flag); + clr_word(mux_word); + } else { + draw_eval_real(rval); + draw_eval_expr_into_integer(mux, 3); + } + break; + case IVL_VT_STRING: + assert(ivl_stmt_opcode(net) == 0); + draw_eval_string(rval); + draw_eval_expr_into_integer(mux, 3); + break; + case IVL_VT_BOOL: + case IVL_VT_LOGIC: + if (ivl_stmt_opcode(net) != 0) { + int mux_word = allocate_word(); + int flag = allocate_flag(); + + draw_eval_expr_into_integer(mux, 3); + fprintf(vvp_out, " %%ix/mov %d, 3;\n", mux_word); + fprintf(vvp_out, " %%flag_mov %u, 4;\n", flag); + fprintf(vvp_out, " %%load/dar/vec4 v%p_0;\n", var); + draw_eval_vec4(rval); + resize_vec4_wid(rval, ivl_stmt_lwidth(net)); + draw_stmt_assign_vector_opcode(ivl_stmt_opcode(net), + ivl_expr_signed(rval)); + fprintf(vvp_out, " %%flag_mov 4, %d;\n", flag); + fprintf(vvp_out, " %%ix/mov 3, %d;\n", mux_word); + clr_flag(flag); + clr_word(mux_word); + } else { + draw_eval_vec4(rval); + resize_vec4_wid(rval, ivl_stmt_lwidth(net)); + draw_eval_expr_into_integer(mux, 3); + } + break; + default: + assert(0); + break; + } +} + static int show_stmt_assign_sig_darray(ivl_statement_t net) { int errors = 0; @@ -1030,41 +1109,35 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net) 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 %store/dar/r 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) { - draw_eval_string(rval); - /* The %store/dar/str 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); - resize_vec4_wid(rval, ivl_stmt_lwidth(net)); - /* 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); - + if (ivl_lval_idx(lval)) { + show_stmt_assign_sig_darray_queue_mux(net); + switch (ivl_type_base(element_type)) { + case IVL_VT_REAL: + fprintf(vvp_out, " %%store/dar/r v%p_0;\n", var); + break; + case IVL_VT_STRING: + fprintf(vvp_out, " %%store/dar/str v%p_0;\n", var); + break; + case IVL_VT_BOOL: + case IVL_VT_LOGIC: + fprintf(vvp_out, " %%store/dar/vec4 v%p_0;\n", var); + break; + default: + assert(0); + break; + } } else if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) { + assert(ivl_stmt_opcode(net) == 0); /* 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 if (ivl_expr_type(rval) == IVL_EX_NEW) { + assert(ivl_stmt_opcode(net) == 0); // There is no l-value mux, and the r-value expression is // a "new" expression. Handle this by simply storing the // new object to the lval. @@ -1074,6 +1147,7 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net) ivl_signal_basename(var)); } else if (ivl_expr_type(rval) == IVL_EX_SIGNAL) { + assert(ivl_stmt_opcode(net) == 0); // There is no l-value mux, and the r-value expression is // a "signal" expression. Store a duplicate into the lvalue @@ -1087,6 +1161,7 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net) fprintf(vvp_out, " %%pop/obj 1, 0;\n"); } else { + assert(ivl_stmt_opcode(net) == 0); // 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. @@ -1177,10 +1252,7 @@ static int show_stmt_assign_sig_queue(ivl_statement_t net) ivl_type_t var_type= ivl_signal_net_type(var); 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); assert(ivl_type_base(var_type) == IVL_VT_QUEUE); @@ -1191,41 +1263,39 @@ static int show_stmt_assign_sig_queue(ivl_statement_t net) fprintf(vvp_out, " %%ix/load %d, %u, 0;\n", idx, ivl_signal_array_count(var)); if (ivl_expr_type(rval) == IVL_EX_NULL) { + assert(ivl_stmt_opcode(net) == 0); errors += draw_eval_object(rval); fprintf(vvp_out, " %%store/obj v%p_0;\n", var); - } else if (mux && (ivl_type_base(element_type) == IVL_VT_REAL)) { - draw_eval_real(rval); - /* The %store/qdar expects the array index to be in - index register 3. */ - draw_eval_expr_into_integer(mux, 3); - fprintf(vvp_out, " %%store/qdar/r v%p_0, %d;\n", var, idx); - - } else if (mux && ivl_type_base(element_type) == IVL_VT_STRING) { - draw_eval_string(rval); - /* The %store/qdar expects the array index to be in - index register 3. */ - draw_eval_expr_into_integer(mux, 3); - fprintf(vvp_out, " %%store/qdar/str v%p_0, %d;\n", var, idx); - - } else if (mux) { // What is left must be some form of vector - assert(ivl_type_base(element_type) == IVL_VT_BOOL || - ivl_type_base(element_type) == IVL_VT_LOGIC); - draw_eval_vec4(rval); - resize_vec4_wid(rval, ivl_stmt_lwidth(net)); - /* The %store/qdar expects the array index to be in - index register 3. */ - draw_eval_expr_into_integer(mux, 3); - fprintf(vvp_out, " %%store/qdar/v v%p_0, %d, %u;\n", var, idx, + } else if (ivl_lval_idx(lval)) { + show_stmt_assign_sig_darray_queue_mux(net); + switch (ivl_type_base(element_type)) { + case IVL_VT_REAL: + fprintf(vvp_out, " %%store/qdar/r v%p_0, %d;\n", var, idx); + break; + case IVL_VT_STRING: + fprintf(vvp_out, " %%store/qdar/str v%p_0, %d;\n", var, idx); + break; + case IVL_VT_BOOL: + case IVL_VT_LOGIC: + fprintf(vvp_out, " %%store/qdar/v v%p_0, %d, %u;\n", var, idx, ivl_type_packed_width(element_type)); - + break; + default: + assert(0); + break; + } } else if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) { + assert(ivl_stmt_opcode(net) == 0); + /* There is no l-value mux, but the r-value is an array pattern. This is a special case of an assignment to the l-value. */ errors += show_stmt_assign_queue_pattern(var, rval, element_type, idx); } else { + assert(ivl_stmt_opcode(net) == 0); + /* 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. */ @@ -1260,39 +1330,43 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net) 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) { + fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); + + if (ivl_type_base(prop_type) == IVL_VT_BOOL || + ivl_type_base(prop_type) == IVL_VT_LOGIC) { assert(ivl_type_packed_dimensions(prop_type) == 0 || (ivl_type_packed_dimensions(prop_type) == 1 && ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0))); + if (ivl_stmt_opcode(net) != 0) { + fprintf(vvp_out, " %%prop/v %d;\n", prop_idx); + } + draw_eval_vec4(rval); - if (ivl_expr_value(rval)!=IVL_VT_BOOL) + if (ivl_type_base(prop_type) == IVL_VT_BOOL && + 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"); + draw_stmt_assign_vector_opcode(ivl_stmt_opcode(net), + ivl_expr_signed(rval)); - } else if (ivl_type_base(prop_type) == IVL_VT_LOGIC) { - assert(ivl_type_packed_dimensions(prop_type) == 0 || - (ivl_type_packed_dimensions(prop_type) == 1 && - 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) { + if (ivl_stmt_opcode(net) != 0) { + fprintf(vvp_out, " %%prop/r %d;\n", prop_idx); + } + /* 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); + + draw_stmt_assign_real_opcode(ivl_stmt_opcode(net)); + fprintf(vvp_out, " %%store/prop/r %d;\n", prop_idx); fprintf(vvp_out, " %%pop/obj 1, 0;\n"); @@ -1302,7 +1376,6 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net) 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"); @@ -1313,7 +1386,6 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net) /* 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); errors += 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"); @@ -1327,7 +1399,6 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net) } /* The property is a class object. */ - fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); errors += 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);