Add regression tests for declaration names shadowing type identifiers

Check that variable and net declaration names can shadow a visible type
identifier. Check this for explicit data type declarations, `var` declarations,
and net declarations.

Check that task and function formal argument names can shadow a visible type
identifier, and that typed arguments still use the visible typedef when an
argument name follows.

Check ambiguous module port declarations where a type identifier can be either
the port name or the port type, with and without dimensions, and that
declaration lists continue to use the type selected by the first ambiguous
declarator. Cover both ANSI and non-ANSI module port declarations.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
Lars-Peter Clausen 2026-06-25 23:10:50 -07:00
parent 7cffbf440d
commit 89b2c8bd80
9 changed files with 651 additions and 0 deletions

View File

@ -0,0 +1,103 @@
// Check that net names can shadow visible type identifiers.
typedef logic [7:0] T;
typedef int U;
typedef logic [5:0] V;
`define check(value, expected, error) \
if ((value) !== (expected)) begin \
$display("FAILED(%0d). %s", `__LINE__, error); \
$display(" expected %0h, got %0h", expected, value); \
failed = 1'b1; \
end
module net_name(output reg failed);
wire T = 1'b1;
initial begin
failed = 1'b0;
`check(T, 1'b1, "wire T did not declare a one-bit net");
end
endmodule
module net_list(output reg failed);
wire T, U;
assign T = 1'b0;
assign U = 1'b1;
initial begin
failed = 1'b0;
`check(T, 1'b0, "type identifier net list first value mismatch");
`check(U, 1'b1, "type identifier net list continuation mismatch");
end
endmodule
module net_array(output reg failed);
wire T [1:0];
assign T[0] = 1'b0;
assign T[1] = 1'b1;
initial begin
failed = 1'b0;
`check(T[0], 1'b0, "type identifier net array first value mismatch");
`check(T[1], 1'b1, "type identifier net array second value mismatch");
end
endmodule
module net_type(output reg failed);
wire T x = 8'ha5;
wire T [1:0] y = 16'h5aa5;
wire V v0, V;
wire T T;
assign v0 = 6'h2a;
assign V = 6'h15;
assign T = 8'h3c;
initial begin
failed = 1'b0;
`check($bits(x), 8, "typed net declaration width regressed");
`check(x, 8'ha5, "typed net declaration value regressed");
`check($bits(y), 16, "typed packed net declaration width regressed");
`check(y, 16'h5aa5, "typed packed net declaration value regressed");
`check($bits(v0), 6, "type identifier net declaration list first width mismatch");
`check($bits(V), 6, "type identifier net declaration list did not allow typedef name as continuation");
`check(V, 6'h15, "type identifier net declaration list value mismatch");
`check($bits(T), 8, "type-name net declaration did not keep typedef type");
`check(T, 8'h3c, "type-name net declaration value mismatch");
end
endmodule
module test;
reg failed;
wire f0;
wire f1;
wire f2;
wire f3;
net_name m0(f0);
net_list m1(f1);
net_array m2(f2);
net_type m3(f3);
initial begin
failed = 1'b0;
#1;
`check(f0, 1'b0, "wire T module failed");
`check(f1, 1'b0, "wire T, U module failed");
`check(f2, 1'b0, "wire T array module failed");
`check(f3, 1'b0, "typed wire T module failed");
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,236 @@
// Check that module port names can shadow visible type identifiers.
typedef logic [3:0] T;
package p;
typedef logic [5:0] PT;
endpackage
`define check(value, expected, error) \
if ((value) !== (expected)) begin \
$display("FAILED(%0d). %s", `__LINE__, error); \
$display(" expected %0h, got %0h", expected, value); \
failed = 1'b1; \
end
module ansi_name(input T);
endmodule
module ansi_type(input T x);
endmodule
module ansi_name_dim(input T [1:0]);
endmodule
module ansi_type_dim(input T [1:0] x);
endmodule
module ansi_name_list(input T, U);
endmodule
module ansi_type_list(input T x, y);
endmodule
module ansi_type_list_shadow(input T x, T);
endmodule
module ansi_type_name(input T T, output logic ok);
initial ok = ($bits(T) == 4);
endmodule
module ansi_type_redecl(input n, T x);
endmodule
module ansi_type_redecl_dim(input n, T [1:0] x);
endmodule
module ansi_name_redecl_dim(input n, T [1:0]);
endmodule
module ansi_pkg_type_redecl(input n, p::PT x);
endmodule
module ansi_pkg_type_redecl_dim(input n, p::PT [1:0] x);
endmodule
module decl_name(T);
input T;
endmodule
module decl_type(x);
input T x;
endmodule
module decl_type_dim(x);
input T [1:0] x;
endmodule
module decl_external(.T(x));
input x;
endmodule
module decl_name_list(T, U);
input T, U;
endmodule
module decl_type_list(x, y);
input T x, y;
endmodule
module decl_type_list_shadow(x, T);
input T x, T;
endmodule
module decl_type_name(T, ok);
input T T;
output logic ok;
initial ok = ($bits(T) == 4);
endmodule
module test;
reg failed;
logic n;
T t;
logic n_dim [1:0];
T [1:0] t_dim;
logic n0, n1;
T t0, t1;
logic rn;
T rt;
T [1:0] rt_dim;
logic rn_dim;
logic rt_name_dim [1:0];
logic rp_n;
logic [5:0] rp_t;
logic rp_dim_n;
logic [1:0][5:0] rp_t_dim;
logic d_n;
T d_t;
T [1:0] d_t_dim;
logic d_ext;
logic d_n0, d_n1;
T d_t0, d_t1;
T s_t0, s_t1;
T d_s_t0, d_s_t1;
T p_tn;
T d_p_tn;
logic p_tn_ok;
logic d_p_tn_ok;
ansi_name m0(n);
ansi_type m1(t);
ansi_name_dim m2(n_dim);
ansi_type_dim m3(t_dim);
ansi_name_list m4(n0, n1);
ansi_type_list m5(t0, t1);
ansi_type_list_shadow m17(s_t0, s_t1);
ansi_type_name m19(p_tn, p_tn_ok);
ansi_type_redecl m12(rn, rt);
ansi_type_redecl_dim m13(rn, rt_dim);
ansi_name_redecl_dim m14(rn_dim, rt_name_dim);
ansi_pkg_type_redecl m15(rp_n, rp_t);
ansi_pkg_type_redecl_dim m16(rp_dim_n, rp_t_dim);
decl_name m6(d_n);
decl_type m7(d_t);
decl_type_dim m8(d_t_dim);
decl_external m9(d_ext);
decl_name_list m10(d_n0, d_n1);
decl_type_list m11(d_t0, d_t1);
decl_type_list_shadow m18(d_s_t0, d_s_t1);
decl_type_name m20(d_p_tn, d_p_tn_ok);
initial begin
failed = 1'b0;
n = 1'b1;
t = 4'ha;
n_dim[0] = 1'b0;
n_dim[1] = 1'b1;
t_dim[0] = 4'h3;
t_dim[1] = 4'hc;
n0 = 1'b0;
n1 = 1'b1;
t0 = 4'h5;
t1 = 4'ha;
s_t0 = 4'h6;
s_t1 = 4'h9;
p_tn = 4'h3;
rn = 1'b1;
rt = 4'hc;
rt_dim[0] = 4'h3;
rt_dim[1] = 4'ha;
rn_dim = 1'b0;
rt_name_dim[0] = 1'b1;
rt_name_dim[1] = 1'b0;
rp_n = 1'b1;
rp_t = 6'h2a;
rp_dim_n = 1'b0;
rp_t_dim[0] = 6'h15;
rp_t_dim[1] = 6'h2a;
d_n = 1'b1;
d_t = 4'h6;
d_t_dim[0] = 4'h7;
d_t_dim[1] = 4'h8;
d_ext = 1'b0;
d_n0 = 1'b1;
d_n1 = 1'b0;
d_t0 = 4'h9;
d_t1 = 4'h6;
d_s_t0 = 4'h5;
d_s_t1 = 4'ha;
d_p_tn = 4'hc;
#1;
`check($bits(n), 1, "input T was not parsed as a port name");
`check($bits(t), 4, "input T x was not parsed as a typed port");
`check($bits(n_dim), 2, "input T [1:0] was not parsed as a port array");
`check($bits(t_dim), 8, "input T [1:0] x was not parsed as a typed port array");
`check($bits(n0), 1, "input T, U first port did not keep implicit type");
`check($bits(n1), 1, "input T, U continuation did not keep implicit type");
`check($bits(t0), 4, "input T x, y first port did not keep typedef type");
`check($bits(t1), 4, "input T x, y continuation did not keep typedef type");
`check(t0, 4'h5, "Typed port list first value mismatch");
`check(t1, 4'ha, "Typed port list continuation mismatch");
`check($bits(s_t0), 4, "input T x, T first port did not keep typedef type");
`check($bits(s_t1), 4, "input T x, T continuation did not allow typedef name as port name");
`check(s_t1, 4'h9, "Typed port list shadowing value mismatch");
`check($bits(p_tn), 4, "input T T did not keep typedef type");
`check(p_tn_ok, 1'b1, "input T T was not available as a typed port");
`check($bits(rn), 1, "input n, T x first port did not keep implicit type");
`check($bits(rt), 4, "input n, T x second port did not keep typedef type");
`check(rt, 4'hc, "Inherited-direction typedef port value mismatch");
`check($bits(rt_dim), 8, "input n, T [1:0] x did not keep typedef packed dimensions");
`check(rt_dim[0], 4'h3, "Inherited-direction typedef packed array value mismatch");
`check(rt_dim[1], 4'ha, "Inherited-direction typedef packed array value mismatch");
`check($bits(rn_dim), 1, "input n, T [1:0] first port did not keep implicit type");
`check($bits(rt_name_dim), 2, "input n, T [1:0] second port was not parsed as a port array");
`check($bits(rp_t), 6, "input n, p::PT x second port did not keep package typedef type");
`check(rp_t, 6'h2a, "Inherited-direction package typedef port value mismatch");
`check($bits(rp_t_dim), 12, "input n, p::PT [1:0] x did not keep package typedef packed dimensions");
`check(rp_t_dim[0], 6'h15, "Inherited-direction package typedef packed array value mismatch");
`check(rp_t_dim[1], 6'h2a, "Inherited-direction package typedef packed array value mismatch");
`check($bits(d_n), 1, "input T was not parsed as a port declaration name");
`check($bits(d_t), 4, "input T x was not parsed as a typed port declaration");
`check($bits(d_t_dim), 8, "input T [1:0] x was not parsed as a typed port declaration array");
`check($bits(d_ext), 1, ".T(x) was not parsed as an external port name");
`check($bits(d_n0), 1, "input T, U first declaration did not keep implicit type");
`check($bits(d_n1), 1, "input T, U continuation declaration did not keep implicit type");
`check($bits(d_t0), 4, "input T x, y first declaration did not keep typedef type");
`check($bits(d_t1), 4, "input T x, y continuation declaration did not keep typedef type");
`check(d_t0, 4'h9, "Typed port declaration list first value mismatch");
`check(d_t1, 4'h6, "Typed port declaration list continuation mismatch");
`check($bits(d_s_t0), 4, "input T x, T first declaration did not keep typedef type");
`check($bits(d_s_t1), 4, "input T x, T declaration did not allow typedef name as port name");
`check(d_s_t1, 4'ha, "Typed port declaration list shadowing value mismatch");
`check($bits(d_p_tn), 4, "non-ANSI input T T did not keep typedef type");
`check(d_p_tn_ok, 1'b1, "non-ANSI input T T was not available as a typed port");
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,120 @@
// Check that task and function argument names can shadow visible type identifiers.
typedef int T;
module test;
reg failed;
`define check(value, expected, error) \
if ((value) !== (expected)) begin \
$display("FAILED(%0d). %s", `__LINE__, error); \
$display(" expected %0h, got %0h", expected, value); \
failed = 1'b1; \
end
function int f_name(input T);
return ($bits(T) == 1 && T === 1'b1) ? 32'd33 : -1;
endfunction
function int f_type(input T value);
return ($bits(value) == 32) ? value : -1;
endfunction
function int f_type_list(input T value, T);
return $bits(value) + $bits(T);
endfunction
function int f_type_name(input T T);
return $bits(T);
endfunction
function int f_decl_name;
input T;
return $bits(T);
endfunction
function int f_decl_type;
input T value;
return $bits(value);
endfunction
function int f_decl_type_name;
input T T;
return $bits(T);
endfunction
task t_name(input T, output int value);
value = ($bits(T) == 1 && T === 1'b1) ? 32'd44 : -1;
endtask
task t_type(input T value, output int result);
result = ($bits(value) == 32) ? value : -1;
endtask
task t_type_list(input T value, T, output int result);
result = $bits(value) + $bits(T);
endtask
task t_type_name(input T T, output int value);
value = $bits(T);
endtask
task t_decl_name;
input T;
output int value;
value = $bits(T);
endtask
task t_decl_type;
input T value;
output int result;
result = $bits(value);
endtask
task t_decl_type_name;
input T T;
output int value;
value = $bits(T);
endtask
initial begin
int r0;
int r1;
int r2;
int r3;
int r4;
int r5;
int r6;
failed = 1'b0;
t_name(1'b1, r0);
t_type(32'd55, r1);
t_type_list(32'd11, 32'd22, r2);
t_decl_name(1'b1, r3);
t_decl_type(32'd33, r4);
t_type_name(32'd44, r5);
t_decl_type_name(32'd55, r6);
`check(f_name(1'b1), 32'd33, "Function argument did not hide typedef");
`check(f_type(32'd66), 32'd66, "Function typed argument regressed");
`check(f_type_list(32'd11, 32'd22), 64, "Function typed argument list shadowing mismatch");
`check(f_type_name(32'd33), 32, "Function type-name argument did not keep typedef type");
`check(f_decl_name(1'b1), 1, "Function non-ANSI argument did not hide typedef");
`check(f_decl_type(32'd66), 32, "Function non-ANSI typed argument regressed");
`check(f_decl_type_name(32'd77), 32, "Function non-ANSI type-name argument did not keep typedef type");
`check(r0, 32'd44, "Task argument did not hide typedef");
`check(r1, 32'd55, "Task typed argument regressed");
`check(r2, 64, "Task typed argument list shadowing mismatch");
`check(r3, 1, "Task non-ANSI argument did not hide typedef");
`check(r4, 32, "Task non-ANSI typed argument regressed");
`check(r5, 32, "Task type-name argument did not keep typedef type");
`check(r6, 32, "Task non-ANSI type-name argument did not keep typedef type");
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,152 @@
// Check that variable names can shadow visible type identifiers.
typedef logic [7:0] T;
typedef int V;
typedef int W;
typedef logic [6:0] A;
typedef logic [5:0] B;
typedef logic [4:0] C;
typedef logic [3:0] D;
typedef logic [2:0] E;
typedef logic [1:0] F;
typedef logic [2:0] G;
typedef logic [3:0] H;
typedef logic [4:0] I;
typedef logic [2:0] P;
bit X;
package p;
var C;
var D x, D;
var P P;
endpackage
module test;
reg failed;
`define check(value, expected, error) \
if ((value) !== (expected)) begin \
$display("FAILED(%0d). %s", `__LINE__, error); \
$display(" expected %0h, got %0h", expected, value); \
failed = 1'b1; \
end
typedef logic [3:0] X;
T outer;
T a, b;
A a0, A;
E E;
int T, U;
var V;
var B b0, B;
var F F;
X x;
function int f;
int T;
T = 32'd11;
return T;
endfunction
function int f_type_name;
H H;
H = 4'ha;
return $bits(H) + H;
endfunction
task t(output int value);
int T;
T = 32'd22;
value = T;
endtask
task t_type_name(output int value);
I I;
I = 5'h15;
value = $bits(I) + I;
endtask
initial begin
int r;
int r_type_name;
int tr_type_name;
var W;
failed = 1'b0;
outer = 8'ha5;
a = 8'h33;
b = 8'hcc;
a0 = 7'h2a;
A = 7'h15;
E = 3'h5;
T = 32'd23;
U = 32'd41;
V = 1'b1;
b0 = 6'h2a;
B = 6'h15;
F = 2'h2;
W = 1'b0;
x = 4'hc;
t(r);
t_type_name(tr_type_name);
begin : block_scope
int T;
T = 32'd7;
`check(T, 32'd7, "Block declaration did not hide typedef");
end
begin : block_type_name
G G;
G = 3'h3;
`check($bits(G), 3, "Block type-name declaration did not keep typedef type");
`check(G, 3'h3, "Block type-name declaration value mismatch");
end
r_type_name = f_type_name();
`check(outer, 8'ha5, "Typedef value changed");
`check(T, 32'd23, "Module declaration did not hide typedef");
`check(U, 32'd41, "Declaration list continuation mismatch");
`check($bits(V), 1, "Module var declaration did not hide typedef width");
`check(V, 1'b1, "Module var declaration did not hide typedef value");
`check($bits(W), 1, "Block var declaration did not hide typedef width");
`check(W, 1'b0, "Block var declaration did not hide typedef value");
`check(a, 8'h33, "Type declaration list first value mismatch");
`check(b, 8'hcc, "Type declaration list continuation mismatch");
`check($bits(a0), 7, "Type declaration list did not keep typedef type");
`check($bits(A), 7, "Type declaration list did not allow typedef name as continuation");
`check(A, 7'h15, "Type declaration list shadowing value mismatch");
`check($bits(E), 3, "Type-name declaration did not keep typedef type");
`check(E, 3'h5, "Type-name declaration value mismatch");
`check($bits(b0), 6, "Var declaration list did not keep typedef type");
`check($bits(B), 6, "Var declaration list did not allow typedef name as continuation");
`check(B, 6'h15, "Var declaration list shadowing value mismatch");
`check($bits(F), 2, "Var type-name declaration did not keep typedef type");
`check(F, 2'h2, "Var type-name declaration value mismatch");
`check($bits(p::C), 1, "Package var declaration did not hide typedef width");
`check($bits(p::x), 4, "Package type declaration list first width mismatch");
`check($bits(p::D), 4, "Package type declaration list did not allow typedef name as continuation");
`check($bits(p::P), 3, "Package type-name declaration did not keep typedef type");
`check(f(), 32'd11, "Function declaration did not hide typedef");
`check(r_type_name, 14, "Function type-name declaration mismatch");
`check(r, 32'd22, "Task declaration did not hide typedef");
`check(tr_type_name, 26, "Task type-name declaration mismatch");
`check($bits(x), 4, "Local typedef did not hide outer identifier");
`check(x, 4'hc, "Local typedef value mismatch");
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -385,8 +385,12 @@ sv_type_identifier_foreach_name vvp_tests/sv_type_identifier_foreach_name.json
sv_type_identifier_genvar_name vvp_tests/sv_type_identifier_genvar_name.json
sv_type_identifier_modport_name vvp_tests/sv_type_identifier_modport_name.json
sv_type_identifier_module_name vvp_tests/sv_type_identifier_module_name.json
sv_type_identifier_net_name vvp_tests/sv_type_identifier_net_name.json
sv_type_identifier_package_item vvp_tests/sv_type_identifier_package_item.json
sv_type_identifier_port_name vvp_tests/sv_type_identifier_port_name.json
sv_type_identifier_specparam_name vvp_tests/sv_type_identifier_specparam_name.json
sv_type_identifier_task_function_argument_name vvp_tests/sv_type_identifier_task_function_argument_name.json
sv_type_identifier_variable_name vvp_tests/sv_type_identifier_variable_name.json
sv_type_param_restrict_class1 vvp_tests/sv_type_param_restrict_class1.json
sv_type_param_restrict_class2 vvp_tests/sv_type_param_restrict_class2.json
sv_type_param_restrict_class_fail1 vvp_tests/sv_type_param_restrict_class_fail1.json

View File

@ -0,0 +1,9 @@
{
"type" : "normal",
"source" : "sv_type_identifier_net_name.v",
"iverilog-args" : [ "-g2005-sv" ],
"vlog95" : {
"__comment" : "Typedefs and SystemVerilog net types are SystemVerilog",
"type" : "CE"
}
}

View File

@ -0,0 +1,9 @@
{
"type" : "normal",
"source" : "sv_type_identifier_port_name.v",
"iverilog-args" : [ "-g2005-sv" ],
"vlog95" : {
"__comment" : "Typedefs and ANSI ports are SystemVerilog",
"type" : "CE"
}
}

View File

@ -0,0 +1,9 @@
{
"type" : "normal",
"source" : "sv_type_identifier_task_function_argument_name.v",
"iverilog-args" : [ "-g2005-sv" ],
"vlog95" : {
"__comment" : "Typedefs and task/function arguments are SystemVerilog",
"type" : "CE"
}
}

View File

@ -0,0 +1,9 @@
{
"type" : "normal",
"source" : "sv_type_identifier_variable_name.v",
"iverilog-args" : [ "-g2005-sv" ],
"vlog95" : {
"__comment" : "Typedefs and block/task scope are SystemVerilog",
"type" : "CE"
}
}