From 60b6435653ebe6ee146cb23f6ca1fdec8adfdf2b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 5 Jan 2025 08:19:51 -0800 Subject: [PATCH 1/2] tgt-vvp: Support nested lvalues for all property types Currently nested lvalues are only supported for vector typed properties. Refactor the code to also support other types. Signed-off-by: Lars-Peter Clausen --- tgt-vvp/stmt_assign.c | 49 +++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 94aed6242..23425eac2 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -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,17 +1309,14 @@ 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 sig_type = draw_lval_expr(lval); ivl_type_t prop_type = ivl_type_prop_type(sig_type, prop_idx); - 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 || @@ -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); } From e2008c9c0e5237772afc11d6dc6c882f870f8bc2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 5 Jan 2025 15:35:21 -0800 Subject: [PATCH 2/2] Add regression tests for nested lvalue object properties Check that nested object properties of different types are supported as lvalues. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/sv_class_prop_nest_darray1.v | 40 +++++++++++++++++++ ivtest/ivltests/sv_class_prop_nest_obj1.v | 38 ++++++++++++++++++ ivtest/ivltests/sv_class_prop_nest_real1.v | 34 ++++++++++++++++ ivtest/ivltests/sv_class_prop_nest_str1.v | 34 ++++++++++++++++ ivtest/ivltests/sv_class_prop_nest_vec1.v | 34 ++++++++++++++++ ivtest/regress-vvp.list | 5 +++ .../vvp_tests/sv_class_prop_nest_darray1.json | 5 +++ ivtest/vvp_tests/sv_class_prop_nest_obj1.json | 5 +++ .../vvp_tests/sv_class_prop_nest_real1.json | 5 +++ ivtest/vvp_tests/sv_class_prop_nest_str1.json | 5 +++ ivtest/vvp_tests/sv_class_prop_nest_vec1.json | 5 +++ 11 files changed, 210 insertions(+) create mode 100644 ivtest/ivltests/sv_class_prop_nest_darray1.v create mode 100644 ivtest/ivltests/sv_class_prop_nest_obj1.v create mode 100644 ivtest/ivltests/sv_class_prop_nest_real1.v create mode 100644 ivtest/ivltests/sv_class_prop_nest_str1.v create mode 100644 ivtest/ivltests/sv_class_prop_nest_vec1.v create mode 100644 ivtest/vvp_tests/sv_class_prop_nest_darray1.json create mode 100644 ivtest/vvp_tests/sv_class_prop_nest_obj1.json create mode 100644 ivtest/vvp_tests/sv_class_prop_nest_real1.json create mode 100644 ivtest/vvp_tests/sv_class_prop_nest_str1.json create mode 100644 ivtest/vvp_tests/sv_class_prop_nest_vec1.json diff --git a/ivtest/ivltests/sv_class_prop_nest_darray1.v b/ivtest/ivltests/sv_class_prop_nest_darray1.v new file mode 100644 index 000000000..a85d65b09 --- /dev/null +++ b/ivtest/ivltests/sv_class_prop_nest_darray1.v @@ -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 diff --git a/ivtest/ivltests/sv_class_prop_nest_obj1.v b/ivtest/ivltests/sv_class_prop_nest_obj1.v new file mode 100644 index 000000000..69f69408b --- /dev/null +++ b/ivtest/ivltests/sv_class_prop_nest_obj1.v @@ -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 diff --git a/ivtest/ivltests/sv_class_prop_nest_real1.v b/ivtest/ivltests/sv_class_prop_nest_real1.v new file mode 100644 index 000000000..ba42ecc26 --- /dev/null +++ b/ivtest/ivltests/sv_class_prop_nest_real1.v @@ -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 diff --git a/ivtest/ivltests/sv_class_prop_nest_str1.v b/ivtest/ivltests/sv_class_prop_nest_str1.v new file mode 100644 index 000000000..922334b49 --- /dev/null +++ b/ivtest/ivltests/sv_class_prop_nest_str1.v @@ -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 diff --git a/ivtest/ivltests/sv_class_prop_nest_vec1.v b/ivtest/ivltests/sv_class_prop_nest_vec1.v new file mode 100644 index 000000000..55d104eef --- /dev/null +++ b/ivtest/ivltests/sv_class_prop_nest_vec1.v @@ -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 diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index dcba81515..51fa355f8 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -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 diff --git a/ivtest/vvp_tests/sv_class_prop_nest_darray1.json b/ivtest/vvp_tests/sv_class_prop_nest_darray1.json new file mode 100644 index 000000000..b03d35594 --- /dev/null +++ b/ivtest/vvp_tests/sv_class_prop_nest_darray1.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_class_prop_nest_darray1.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_class_prop_nest_obj1.json b/ivtest/vvp_tests/sv_class_prop_nest_obj1.json new file mode 100644 index 000000000..f7b9c861f --- /dev/null +++ b/ivtest/vvp_tests/sv_class_prop_nest_obj1.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_class_prop_nest_obj1.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_class_prop_nest_real1.json b/ivtest/vvp_tests/sv_class_prop_nest_real1.json new file mode 100644 index 000000000..86605f4ad --- /dev/null +++ b/ivtest/vvp_tests/sv_class_prop_nest_real1.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_class_prop_nest_real1.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_class_prop_nest_str1.json b/ivtest/vvp_tests/sv_class_prop_nest_str1.json new file mode 100644 index 000000000..31fad1ee1 --- /dev/null +++ b/ivtest/vvp_tests/sv_class_prop_nest_str1.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_class_prop_nest_str1.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_class_prop_nest_vec1.json b/ivtest/vvp_tests/sv_class_prop_nest_vec1.json new file mode 100644 index 000000000..a6617fd8e --- /dev/null +++ b/ivtest/vvp_tests/sv_class_prop_nest_vec1.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_class_prop_nest_vec1.v", + "iverilog-args" : [ "-g2005-sv" ] +}