Merge pull request #1199 from larsclausen/assignment-op
Add support for assignment ops on class properties and dynamic array or queue elements
This commit is contained in:
commit
b794b9cc26
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_class_prop_assign_op1.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_class_prop_assign_op2.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_darray_assign_op.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "sv_queue_assign_op.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ]
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue