From e5f2975a973e61607e4dae32d14a3752a3cbe447 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 15 Aug 2026 18:43:59 -0700 Subject: [PATCH] Add regression tests for compilation-unit lookup order Check that same-named scopes in the enclosing instance hierarchy do not interfere with lookup of compilation-unit variables, parameters, named events, and imported variables. Cover expressions, procedural l-values, implicit and wildcard port connections, and lookup from module and nested function scopes. Check task and function calls, including method receivers and chained calls. Verify that receiver prefixes follow ordinary lexical ordering while direct, imported, and chained compilation-unit function names can be declared after their references. Check the enclosing-instance fallback when the compilation unit has no match. Signed-off-by: Lars-Peter Clausen --- .../sv_function_call_chain_unit_precedence.v | 44 ++++++++++++++ .../sv_function_call_receiver_unit_order.v | 58 +++++++++++++++++++ .../sv_function_call_unit_import_precedence.v | 34 +++++++++++ .../sv_function_call_unit_precedence.v | 46 +++++++++++++++ .../sv_task_call_receiver_unit_precedence.v | 38 ++++++++++++ .../ivltests/sv_unit_lvalue_instance_name.v | 28 +++++++++ .../sv_unit_member_instance_precedence.v | 44 ++++++++++++++ .../sv_unit_nested_scope_instance_name.v | 30 ++++++++++ ivtest/ivltests/sv_unit_port_instance_name.v | 44 ++++++++++++++ .../sv_unit_symbol_kinds_instance_name.v | 56 ++++++++++++++++++ ivtest/regress-vvp.list | 10 ++++ ...v_function_call_chain_unit_precedence.json | 9 +++ .../sv_function_call_receiver_unit_order.json | 9 +++ ..._function_call_unit_import_precedence.json | 5 ++ .../sv_function_call_unit_precedence.json | 5 ++ ...sv_task_call_receiver_unit_precedence.json | 9 +++ .../sv_unit_lvalue_instance_name.json | 5 ++ .../sv_unit_member_instance_precedence.json | 9 +++ .../sv_unit_nested_scope_instance_name.json | 5 ++ .../vvp_tests/sv_unit_port_instance_name.json | 9 +++ .../sv_unit_symbol_kinds_instance_name.json | 5 ++ 21 files changed, 502 insertions(+) create mode 100644 ivtest/ivltests/sv_function_call_chain_unit_precedence.v create mode 100644 ivtest/ivltests/sv_function_call_receiver_unit_order.v create mode 100644 ivtest/ivltests/sv_function_call_unit_import_precedence.v create mode 100644 ivtest/ivltests/sv_function_call_unit_precedence.v create mode 100644 ivtest/ivltests/sv_task_call_receiver_unit_precedence.v create mode 100644 ivtest/ivltests/sv_unit_lvalue_instance_name.v create mode 100644 ivtest/ivltests/sv_unit_member_instance_precedence.v create mode 100644 ivtest/ivltests/sv_unit_nested_scope_instance_name.v create mode 100644 ivtest/ivltests/sv_unit_port_instance_name.v create mode 100644 ivtest/ivltests/sv_unit_symbol_kinds_instance_name.v create mode 100644 ivtest/vvp_tests/sv_function_call_chain_unit_precedence.json create mode 100644 ivtest/vvp_tests/sv_function_call_receiver_unit_order.json create mode 100644 ivtest/vvp_tests/sv_function_call_unit_import_precedence.json create mode 100644 ivtest/vvp_tests/sv_function_call_unit_precedence.json create mode 100644 ivtest/vvp_tests/sv_task_call_receiver_unit_precedence.json create mode 100644 ivtest/vvp_tests/sv_unit_lvalue_instance_name.json create mode 100644 ivtest/vvp_tests/sv_unit_member_instance_precedence.json create mode 100644 ivtest/vvp_tests/sv_unit_nested_scope_instance_name.json create mode 100644 ivtest/vvp_tests/sv_unit_port_instance_name.json create mode 100644 ivtest/vvp_tests/sv_unit_symbol_kinds_instance_name.json diff --git a/ivtest/ivltests/sv_function_call_chain_unit_precedence.v b/ivtest/ivltests/sv_function_call_chain_unit_precedence.v new file mode 100644 index 000000000..aa90a99a3 --- /dev/null +++ b/ivtest/ivltests/sv_function_call_chain_unit_precedence.v @@ -0,0 +1,44 @@ +// Check that compilation-unit function lookup is used at the start of a +// chained call. + +class unit_class; + + function integer value; + value = 1; + endfunction + +endclass + +module child; + + initial begin + if (make_object().value() == 1) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule + +function unit_class make_object; + make_object = new; +endfunction + +module test; + + class instance_class; + + function integer value; + value = 2; + endfunction + + endclass + + child i_child(); + + function instance_class make_object; + make_object = new; + endfunction + +endmodule diff --git a/ivtest/ivltests/sv_function_call_receiver_unit_order.v b/ivtest/ivltests/sv_function_call_receiver_unit_order.v new file mode 100644 index 000000000..339eac646 --- /dev/null +++ b/ivtest/ivltests/sv_function_call_receiver_unit_order.v @@ -0,0 +1,58 @@ +// Check lexical ordering for the receiver of a function call. + +class C; + + function integer value; + value = 11; + endfunction + +endclass + +C before_object = new; + +module holder; + + function integer value; + value = 22; + endfunction + +endmodule + +module child; + + integer before_value; + integer after_value; + reg failed; + + `define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, \ + `"val`", exp, val); \ + failed = 1'b1; \ + end + + initial begin + failed = 1'b0; + + before_value = before_object.value(); + after_value = after_object.value(); + + `check(before_value, 11) + `check(after_value, 22) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule + +module test; + + holder before_object(); + holder after_object(); + child child_instance(); + +endmodule + +C after_object = new; diff --git a/ivtest/ivltests/sv_function_call_unit_import_precedence.v b/ivtest/ivltests/sv_function_call_unit_import_precedence.v new file mode 100644 index 000000000..88f93b282 --- /dev/null +++ b/ivtest/ivltests/sv_function_call_unit_import_precedence.v @@ -0,0 +1,34 @@ +// Check that a function imported into the compilation unit takes precedence +// over a function in an enclosing instance. + +package p; + + function integer value; + value = 1; + endfunction + +endpackage + +module child; + + initial begin + if (value() == 1) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule + +import p::value; + +module test; + + child i_child(); + + function integer value; + value = 2; + endfunction + +endmodule diff --git a/ivtest/ivltests/sv_function_call_unit_precedence.v b/ivtest/ivltests/sv_function_call_unit_precedence.v new file mode 100644 index 000000000..a179af6a2 --- /dev/null +++ b/ivtest/ivltests/sv_function_call_unit_precedence.v @@ -0,0 +1,46 @@ +// Check that a compilation-unit function takes precedence over a function in +// an enclosing instance. + +module child; + + reg failed; + + `define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %h, got %h", `__LINE__, \ + `"val`", exp, val); \ + failed = 1'b1; \ + end + + initial begin + failed = 1'b0; + + `check($bits(value()), 4) + `check(value(), 4'h5) + `check($bits(instance_only()), 3) + `check(instance_only(), 3'h6) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule + +function [3:0] value; + value = 4'h5; +endfunction + +module test; + + child i_child(); + + function [7:0] value; + value = 8'ha5; + endfunction + + function [2:0] instance_only; + instance_only = 3'h6; + endfunction + +endmodule diff --git a/ivtest/ivltests/sv_task_call_receiver_unit_precedence.v b/ivtest/ivltests/sv_task_call_receiver_unit_precedence.v new file mode 100644 index 000000000..7129e8039 --- /dev/null +++ b/ivtest/ivltests/sv_task_call_receiver_unit_precedence.v @@ -0,0 +1,38 @@ +// Check that a compilation-unit object takes precedence over an enclosing +// instance when it is the receiver of a task call. + +class C; + + integer value = 0; + + task set_value; + value = 11; + endtask + +endclass + +C object = new; + +module holder; +endmodule + +module child; + + initial begin + object.set_value(); + + if (object.value !== 11) begin + $display("FAILED: value=%0d", object.value); + end else begin + $display("PASSED"); + end + end + +endmodule + +module test; + + holder object(); + child child_instance(); + +endmodule diff --git a/ivtest/ivltests/sv_unit_lvalue_instance_name.v b/ivtest/ivltests/sv_unit_lvalue_instance_name.v new file mode 100644 index 000000000..46c3ebc90 --- /dev/null +++ b/ivtest/ivltests/sv_unit_lvalue_instance_name.v @@ -0,0 +1,28 @@ +// Check that an enclosing instance name does not affect compilation-unit +// variable lookup for a procedural l-value. + +integer value = 0; + +module holder; +endmodule + +module child; + + initial begin + value = 23; + + if (value !== 23) begin + $display("FAILED: value=%0d", value); + end else begin + $display("PASSED"); + end + end + +endmodule + +module test; + + holder value(); + child child_instance(); + +endmodule diff --git a/ivtest/ivltests/sv_unit_member_instance_precedence.v b/ivtest/ivltests/sv_unit_member_instance_precedence.v new file mode 100644 index 000000000..b5fb3bd14 --- /dev/null +++ b/ivtest/ivltests/sv_unit_member_instance_precedence.v @@ -0,0 +1,44 @@ +// Check that a compilation-unit object takes precedence over an enclosing +// instance when resolving a member reference. + +typedef struct packed { + integer value; +} object_t; + +object_t object = 11; + +module holder; + + integer value = 22; + +endmodule + +module child; + + reg failed; + + `define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, \ + `"val`", exp, val); \ + failed = 1'b1; \ + end + + initial begin + failed = 1'b0; + + `check(object.value, 11) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule + +module test; + + holder object(); + child child_instance(); + +endmodule diff --git a/ivtest/ivltests/sv_unit_nested_scope_instance_name.v b/ivtest/ivltests/sv_unit_nested_scope_instance_name.v new file mode 100644 index 000000000..04e6db8a7 --- /dev/null +++ b/ivtest/ivltests/sv_unit_nested_scope_instance_name.v @@ -0,0 +1,30 @@ +// Check that an enclosing instance name does not affect compilation-unit +// lookup from a nested function scope. + +parameter integer value = 29; + +module holder; +endmodule + +module child; + + function integer read_value; + read_value = value; + endfunction + + initial begin + if (read_value() !== 29) begin + $display("FAILED: value=%0d", read_value()); + end else begin + $display("PASSED"); + end + end + +endmodule + +module test; + + holder value(); + child child_instance(); + +endmodule diff --git a/ivtest/ivltests/sv_unit_port_instance_name.v b/ivtest/ivltests/sv_unit_port_instance_name.v new file mode 100644 index 000000000..673ea4074 --- /dev/null +++ b/ivtest/ivltests/sv_unit_port_instance_name.v @@ -0,0 +1,44 @@ +// Check that enclosing instance names do not affect compilation-unit variable +// lookup for implicit and wildcard port connections. + +reg [31:0] named_value = 41; +reg [31:0] wildcard_value = 43; + +module holder; +endmodule + +module port_target( + input wire [31:0] named_value, + input wire [31:0] wildcard_value, + output wire passed +); + + assign passed = named_value == 32'd41 && wildcard_value == 32'd43; + +endmodule + +module child; + + wire passed; + + port_target target(.named_value, .passed(passed), .*); + + initial begin + #1; + + if (passed !== 1) begin + $display("FAILED"); + end else begin + $display("PASSED"); + end + end + +endmodule + +module test; + + holder named_value(); + holder wildcard_value(); + child child_instance(); + +endmodule diff --git a/ivtest/ivltests/sv_unit_symbol_kinds_instance_name.v b/ivtest/ivltests/sv_unit_symbol_kinds_instance_name.v new file mode 100644 index 000000000..e04d5763d --- /dev/null +++ b/ivtest/ivltests/sv_unit_symbol_kinds_instance_name.v @@ -0,0 +1,56 @@ +// Check that enclosing instance names do not affect compilation-unit lookup +// for parameters, named events, and imported variables. + +package p; + integer imported_value = 53; +endpackage + +import p::*; + +parameter integer parameter_value = 59; + +event event_value; + +module holder; +endmodule + +module child; + + reg event_seen; + reg failed; + + initial begin + event_seen = 1'b0; + failed = 1'b0; + + fork + begin + @event_value; + event_seen = 1'b1; + end + begin + #1 -> event_value; + end + join + + if (imported_value !== 53 || parameter_value !== 59 || !event_seen) begin + failed = 1'b1; + end + + if (failed) begin + $display("FAILED"); + end else begin + $display("PASSED"); + end + end + +endmodule + +module test; + + holder event_value(); + holder imported_value(); + holder parameter_value(); + child child_instance(); + +endmodule diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index ffa554ffe..dca83d3f4 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -358,6 +358,10 @@ sv_foreach10 vvp_tests/sv_foreach10.json sv_fork_prefix_label vvp_tests/sv_fork_prefix_label.json sv_fork_prefix_name_diff_fail vvp_tests/sv_fork_prefix_name_diff_fail.json sv_fork_prefix_name_same_fail vvp_tests/sv_fork_prefix_name_same_fail.json +sv_function_call_chain_unit_precedence vvp_tests/sv_function_call_chain_unit_precedence.json +sv_function_call_receiver_unit_order vvp_tests/sv_function_call_receiver_unit_order.json +sv_function_call_unit_import_precedence vvp_tests/sv_function_call_unit_import_precedence.json +sv_function_call_unit_precedence vvp_tests/sv_function_call_unit_precedence.json sv_interface vvp_tests/sv_interface.json sv_interface_identifier_block_name vvp_tests/sv_interface_identifier_block_name.json sv_interface_identifier_instance_name vvp_tests/sv_interface_identifier_instance_name.json @@ -466,6 +470,7 @@ sv_soft_packed_union vvp_tests/sv_soft_packed_union.json sv_soft_packed_union_fail1 vvp_tests/sv_soft_packed_union_fail1.json sv_string_method_substr_too_few_arg_fail vvp_tests/sv_string_method_substr_too_few_arg_fail.json sv_super_member_fail vvp_tests/sv_super_member_fail.json +sv_task_call_receiver_unit_precedence vvp_tests/sv_task_call_receiver_unit_precedence.json sv_type_identifier_ams_name_fields vvp_tests/sv_type_identifier_ams_name_fields.json sv_type_identifier_assert_item_label vvp_tests/sv_type_identifier_assert_item_label.json sv_type_identifier_assert_label vvp_tests/sv_type_identifier_assert_label.json @@ -525,10 +530,15 @@ sv_type_param_restrict_union1 vvp_tests/sv_type_param_restrict_union1.json sv_type_param_restrict_union2 vvp_tests/sv_type_param_restrict_union2.json sv_type_param_restrict_union_fail1 vvp_tests/sv_type_param_restrict_union_fail1.json sv_type_param_restrict_union_fail2 vvp_tests/sv_type_param_restrict_union_fail2.json +sv_unit_lvalue_instance_name vvp_tests/sv_unit_lvalue_instance_name.json +sv_unit_member_instance_precedence vvp_tests/sv_unit_member_instance_precedence.json +sv_unit_nested_scope_instance_name vvp_tests/sv_unit_nested_scope_instance_name.json sv_unit_order_event_fail vvp_tests/sv_unit_order_event_fail.json sv_unit_order_parameter_fail vvp_tests/sv_unit_order_parameter_fail.json sv_unit_order_valid vvp_tests/sv_unit_order_valid.json sv_unit_order_variable_fail vvp_tests/sv_unit_order_variable_fail.json +sv_unit_port_instance_name vvp_tests/sv_unit_port_instance_name.json +sv_unit_symbol_kinds_instance_name vvp_tests/sv_unit_symbol_kinds_instance_name.json sv_wildcard_import8 vvp_tests/sv_wildcard_import8.json sv_wildcard_port_order vvp_tests/sv_wildcard_port_order.json sv_wildcard_port_order_relaxed vvp_tests/sv_wildcard_port_order_relaxed.json diff --git a/ivtest/vvp_tests/sv_function_call_chain_unit_precedence.json b/ivtest/vvp_tests/sv_function_call_chain_unit_precedence.json new file mode 100644 index 000000000..56157423f --- /dev/null +++ b/ivtest/vvp_tests/sv_function_call_chain_unit_precedence.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_function_call_chain_unit_precedence.v", + "iverilog-args" : [ "-g2012" ], + "vlog95" : { + "__comment" : "Class scopes are not currently translated", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_function_call_receiver_unit_order.json b/ivtest/vvp_tests/sv_function_call_receiver_unit_order.json new file mode 100644 index 000000000..a8014c6f3 --- /dev/null +++ b/ivtest/vvp_tests/sv_function_call_receiver_unit_order.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_function_call_receiver_unit_order.v", + "iverilog-args" : [ "-g2012" ], + "vlog95" : { + "__comment" : "Class scopes are not currently translated", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_function_call_unit_import_precedence.json b/ivtest/vvp_tests/sv_function_call_unit_import_precedence.json new file mode 100644 index 000000000..120a8a53f --- /dev/null +++ b/ivtest/vvp_tests/sv_function_call_unit_import_precedence.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_function_call_unit_import_precedence.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_function_call_unit_precedence.json b/ivtest/vvp_tests/sv_function_call_unit_precedence.json new file mode 100644 index 000000000..80ad63411 --- /dev/null +++ b/ivtest/vvp_tests/sv_function_call_unit_precedence.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_function_call_unit_precedence.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_task_call_receiver_unit_precedence.json b/ivtest/vvp_tests/sv_task_call_receiver_unit_precedence.json new file mode 100644 index 000000000..aa356b540 --- /dev/null +++ b/ivtest/vvp_tests/sv_task_call_receiver_unit_precedence.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_task_call_receiver_unit_precedence.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Class scopes are not currently translated", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_unit_lvalue_instance_name.json b/ivtest/vvp_tests/sv_unit_lvalue_instance_name.json new file mode 100644 index 000000000..d02c17f99 --- /dev/null +++ b/ivtest/vvp_tests/sv_unit_lvalue_instance_name.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_unit_lvalue_instance_name.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_unit_member_instance_precedence.json b/ivtest/vvp_tests/sv_unit_member_instance_precedence.json new file mode 100644 index 000000000..eb900203d --- /dev/null +++ b/ivtest/vvp_tests/sv_unit_member_instance_precedence.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_unit_member_instance_precedence.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Packed structures are not supported", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_unit_nested_scope_instance_name.json b/ivtest/vvp_tests/sv_unit_nested_scope_instance_name.json new file mode 100644 index 000000000..6a1d72fd9 --- /dev/null +++ b/ivtest/vvp_tests/sv_unit_nested_scope_instance_name.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_unit_nested_scope_instance_name.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_unit_port_instance_name.json b/ivtest/vvp_tests/sv_unit_port_instance_name.json new file mode 100644 index 000000000..7b6f9207d --- /dev/null +++ b/ivtest/vvp_tests/sv_unit_port_instance_name.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_unit_port_instance_name.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Compilation-unit implicit port connections are not translated", + "type" : "NI" + } +} diff --git a/ivtest/vvp_tests/sv_unit_symbol_kinds_instance_name.json b/ivtest/vvp_tests/sv_unit_symbol_kinds_instance_name.json new file mode 100644 index 000000000..3750d55a5 --- /dev/null +++ b/ivtest/vvp_tests/sv_unit_symbol_kinds_instance_name.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_unit_symbol_kinds_instance_name.v", + "iverilog-args" : [ "-g2005-sv" ] +}