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 <lars@metafoo.de>
This commit is contained in:
Lars-Peter Clausen 2026-08-15 18:43:59 -07:00
parent 9d7e8e67ab
commit e5f2975a97
21 changed files with 502 additions and 0 deletions

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

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

View File

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

View File

@ -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"
}
}

View File

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

View File

@ -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"
}
}

View File

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

View File

@ -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"
}
}

View File

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