Merge pull request #1201 from larsclausen/nested-lvalue-types

tgt-vvp: Support nested lvalues for all property types
This commit is contained in:
Lars-Peter Clausen 2025-01-07 19:51:37 -08:00 committed by GitHub
commit 27bae7eab1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 230 additions and 31 deletions

View File

@ -0,0 +1,40 @@
// Check that nested dynamic array typed class properties can be used as
// lvalues.
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;
C c;
int d[];
endclass
initial begin
C c1, c2;
int d[];
c1 = new;
c1.c = new;
c2 = c1.c;
d = new[2];
d[0] = 10;
c1.c.d = d;
d = c2.d;
`check(d[0], 10);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,38 @@
// Check that nested object typed class properties can be used as lvalues.
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;
C c;
integer i;
endclass
initial begin
C c1, c2, c3;
c1 = new;
c1.c = new;
c2 = c1.c;
c3 = new;
c3.i = 10;
c1.c.c = c3;
c3 = c2.c;
`check(c3.i, 10);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,34 @@
// Check that nested real typed class properties can be used as lvalues.
module test;
bit failed = 1'b0;
`define check(val, exp) do \
if (val != exp) begin \
$display("FAILED(%0d). '%s' expected %f, got %f", `__LINE__, `"val`", exp, val); \
failed = 1'b1; \
end \
while(0)
class C;
C c;
real r;
endclass
initial begin
C c1, c2;
c1 = new;
c1.c = new;
c2 = c1.c;
c1.c.r = 12.3;
`check(c2.r, 12.3);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,34 @@
// Check that nested string typed class properties can be used as lvalues.
module test;
bit failed = 1'b0;
`define check(val, exp) do \
if (val != exp) begin \
$display("FAILED(%0d). '%s' expected %s, got %s", `__LINE__, `"val`", exp, val); \
failed = 1'b1; \
end \
while(0)
class C;
C c;
string s;
endclass
initial begin
C c1, c2;
c1 = new;
c1.c = new;
c2 = c1.c;
c1.c.s = "Hello";
`check(c2.s, "Hello");
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,34 @@
// Check that nested vector typed class properties can be used as lvalues.
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;
C c;
int i;
endclass
initial begin
C c1, c2;
c1 = new;
c1.c = new;
c2 = c1.c;
c1.c.i = 10;
`check(c2.i, 10);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -225,6 +225,11 @@ 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_class_prop_nest_darray1 vvp_tests/sv_class_prop_nest_darray1.json
sv_class_prop_nest_obj1 vvp_tests/sv_class_prop_nest_obj1.json
sv_class_prop_nest_real1 vvp_tests/sv_class_prop_nest_str1.json
sv_class_prop_nest_str1 vvp_tests/sv_class_prop_nest_real1.json
sv_class_prop_nest_vec1 vvp_tests/sv_class_prop_nest_vec1.json
sv_const1 vvp_tests/sv_const1.json
sv_const2 vvp_tests/sv_const2.json
sv_const3 vvp_tests/sv_const3.json

View File

@ -0,0 +1,5 @@
{
"type" : "normal",
"source" : "sv_class_prop_nest_darray1.v",
"iverilog-args" : [ "-g2005-sv" ]
}

View File

@ -0,0 +1,5 @@
{
"type" : "normal",
"source" : "sv_class_prop_nest_obj1.v",
"iverilog-args" : [ "-g2005-sv" ]
}

View File

@ -0,0 +1,5 @@
{
"type" : "normal",
"source" : "sv_class_prop_nest_real1.v",
"iverilog-args" : [ "-g2005-sv" ]
}

View File

@ -0,0 +1,5 @@
{
"type" : "normal",
"source" : "sv_class_prop_nest_str1.v",
"iverilog-args" : [ "-g2005-sv" ]
}

View File

@ -0,0 +1,5 @@
{
"type" : "normal",
"source" : "sv_class_prop_nest_vec1.v",
"iverilog-args" : [ "-g2005-sv" ]
}

View File

@ -371,25 +371,27 @@ 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);
if (lval_sig) {
fprintf(vvp_out, " %%load/obj v%p_0;\n", lval_sig);
return ivl_signal_net_type(lval_sig);
}
assert (lval_nest);
ivl_type_t sub_type = draw_lval_expr(lval_nest);
assert(ivl_type_base(sub_type) == IVL_VT_CLASS);
if (ivl_lval_idx(lval)) {
if (ivl_lval_idx(lval_nest)) {
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));
int prop_idx = ivl_lval_property_idx(lval_nest);
fprintf(vvp_out, " %%prop/obj %d, 0; Load property %s\n", prop_idx,
ivl_type_prop_name(sub_type, prop_idx));
fprintf(vvp_out, " %%pop/obj 1, 1;\n");
return ivl_type_prop_type(sub_type, ivl_lval_property_idx(lval));
return ivl_type_prop_type(sub_type, prop_idx);
}
/*
@ -407,7 +409,6 @@ 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);
@ -461,19 +462,6 @@ static void store_vec4_to_lval(ivl_statement_t net)
}
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 %d, %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);
@ -1321,16 +1309,13 @@ 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);
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
if (prop_idx >= 0) {
ivl_type_t sig_type = draw_lval_expr(lval);
ivl_type_t prop_type = ivl_type_prop_type(sig_type, prop_idx);
if (ivl_type_base(prop_type) == IVL_VT_BOOL ||
ivl_type_base(prop_type) == IVL_VT_LOGIC) {
@ -1413,6 +1398,9 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
}
} else {
ivl_signal_t sig = ivl_lval_sig(lval);
assert(!ivl_lval_nest(lval));
if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) {
draw_array_pattern(sig, rval, 0);
return 0;
@ -1466,7 +1454,8 @@ int show_stmt_assign(ivl_statement_t net)
return show_stmt_assign_sig_queue(net);
}
if (sig && (ivl_signal_data_type(sig) == IVL_VT_CLASS)) {
if ((sig && (ivl_signal_data_type(sig) == IVL_VT_CLASS)) ||
ivl_lval_nest(lval)) {
return show_stmt_assign_sig_cobject(net);
}