Tests: Add self-checking tests for tagged union features (#6867 partial) (#6869)

This commit is contained in:
Jose Drowne 2026-01-04 10:22:52 -05:00 committed by GitHub
parent e01f0f5e67
commit 883ff01d21
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 1519 additions and 0 deletions

View File

@ -2435,6 +2435,9 @@ class VlTest:
if n:
l1o.append(line)
break # Trunc rest
if re.search(r'This fatal error may be caused', line):
l1o.append(line)
break # Trunc after "This fatal error" line
l1o.append(line)
#
l1s = l1o

View File

@ -0,0 +1,158 @@
%Error-UNSUPPORTED: t/t_tagged_case.v:24:17: Unsupported: tagged union
24 | typedef union tagged {
| ^~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_tagged_case.v:25:5: Unsupported: void (for tagged unions)
25 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_case.v:30:17: Unsupported: tagged union
30 | typedef union tagged packed {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_case.v:31:5: Unsupported: void (for tagged unions)
31 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_case.v:39:17: Unsupported: tagged union
39 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_case.v:40:5: Unsupported: void (for tagged unions)
40 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_case.v:46:17: Unsupported: tagged union
46 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_case.v:50:11: Unsupported: tagged union
50 | union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_case.v:60:17: Unsupported: tagged union
60 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_case.v:61:5: Unsupported: void (for tagged unions)
61 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_case.v:66:17: Unsupported: tagged union
66 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_case.v:67:5: Unsupported: void (for tagged unions)
67 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_case.v:75:17: Unsupported: tagged union
75 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_case.v:76:5: Unsupported: void (for tagged unions)
76 | void Invalid;
| ^~~~
%Warning-SHORTREAL: t/t_tagged_case.v:78:5: Unsupported: shortreal being promoted to real (suggest use real instead)
78 | shortreal ShortRealVal;
| ^~~~~~~~~
... For warning description see https://verilator.org/warn/SHORTREAL?v=latest
... Use "/* verilator lint_off SHORTREAL */" and lint_on around source to disable this message.
%Error-UNSUPPORTED: t/t_tagged_case.v:82:17: Unsupported: tagged union
82 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_case.v:83:5: Unsupported: void (for tagged unions)
83 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_case.v:88:17: Unsupported: tagged union
88 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_case.v:89:5: Unsupported: void (for tagged unions)
89 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_case.v:97:17: Unsupported: tagged union
97 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_case.v:98:5: Unsupported: void (for tagged unions)
98 | void Invalid;
| ^~~~
%Error: t/t_tagged_case.v:122:9: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
122 | v = tagged Invalid;
| ^~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: t/t_tagged_case.v:125:7: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
125 | tagged Invalid : result = 1;
| ^~~~~~
%Error: t/t_tagged_case.v:128:161: syntax error, unexpected while
128 | do if ((result) !== (1)) begin $write("%%Error: %s:%0d: got=%0x exp=%0x (%s !== %s)\n", "t/t_tagged_case.v",128, (result), (1), "result", "1"); $stop; end while(0);;
| ^~~~~
%Error: t/t_tagged_case.v:131:7: syntax error, unexpected '=', expecting '('
131 | v = tagged Valid (123);
| ^
%Error: t/t_tagged_case.v:133:14: syntax error, unexpected matches, expecting IDENTIFIER-for-type
133 | case (v) matches
| ^~~~~~~
%Error: t/t_tagged_case.v:140:8: syntax error, unexpected '=', expecting '('
140 | wt = tagged Wide60 (60'hFEDCBA987654321);
| ^
%Error: t/t_tagged_case.v:142:15: syntax error, unexpected matches, expecting IDENTIFIER-for-type
142 | case (wt) matches
| ^~~~~~~
%Error: t/t_tagged_case.v:150:8: syntax error, unexpected '=', expecting '('
150 | wt = tagged Wide90 (90'hDE_ADBEEFCA_FEBABE12_3456);
| ^
%Error: t/t_tagged_case.v:152:15: syntax error, unexpected matches, expecting IDENTIFIER-for-type
152 | case (wt) matches
| ^~~~~~~
%Error: t/t_tagged_case.v:160:8: syntax error, unexpected '=', expecting '('
160 | wt = tagged Byte8NonZeroLSB (8'hA5);
| ^
%Error: t/t_tagged_case.v:162:15: syntax error, unexpected matches, expecting IDENTIFIER-for-type
162 | case (wt) matches
| ^~~~~~~
%Error: t/t_tagged_case.v:169:8: syntax error, unexpected '=', expecting '('
169 | wt = tagged Word32LittleEndian (32'hDEADBEEF);
| ^
%Error: t/t_tagged_case.v:171:15: syntax error, unexpected matches, expecting IDENTIFIER-for-type
171 | case (wt) matches
| ^~~~~~~
%Error: t/t_tagged_case.v:178:8: syntax error, unexpected '=', expecting '('
178 | at = tagged Arr '{10, 20, 30, 40};
| ^
%Error: t/t_tagged_case.v:180:15: syntax error, unexpected matches, expecting IDENTIFIER-for-type
180 | case (at) matches
| ^~~~~~~
%Error: t/t_tagged_case.v:188:11: syntax error, unexpected '=', expecting '('
188 | instr = tagged Jmp (tagged JmpC '{2'd1, 10'd256});
| ^
%Error: t/t_tagged_case.v:190:18: syntax error, unexpected matches, expecting IDENTIFIER-for-type
190 | case (instr) matches
| ^~~~~~~
%Error: t/t_tagged_case.v:198:9: syntax error, unexpected '=', expecting '('
198 | cht = tagged Invalid;
| ^
%Error: t/t_tagged_case.v:200:16: syntax error, unexpected matches, expecting IDENTIFIER-for-type
200 | case (cht) matches
| ^~~~~~~
%Error: t/t_tagged_case.v:207:9: syntax error, unexpected =-then-new, expecting '('
207 | obj = new(42);
| ^
%Error: t/t_tagged_case.v:210:16: syntax error, unexpected matches, expecting IDENTIFIER-for-type
210 | case (clt) matches
| ^~~~~~~
%Error: t/t_tagged_case.v:217:8: syntax error, unexpected '=', expecting '('
217 | rt = tagged Invalid;
| ^
%Error: t/t_tagged_case.v:219:15: syntax error, unexpected matches, expecting IDENTIFIER-for-type
219 | case (rt) matches
| ^~~~~~~
%Error: t/t_tagged_case.v:226:8: syntax error, unexpected '=', expecting '('
226 | rt = tagged RealVal (3.14159);
| ^
%Error: t/t_tagged_case.v:228:15: syntax error, unexpected matches, expecting IDENTIFIER-for-type
228 | case (rt) matches
| ^~~~~~~
%Error: t/t_tagged_case.v:239:8: syntax error, unexpected '=', expecting '('
239 | rt = tagged ShortRealVal (2.5);
| ^
%Error: t/t_tagged_case.v:241:15: syntax error, unexpected matches, expecting IDENTIFIER-for-type
241 | case (rt) matches
| ^~~~~~~
%Error: t/t_tagged_case.v:252:8: syntax error, unexpected '=', expecting '('
252 | st = tagged Invalid;
| ^
%Error: t/t_tagged_case.v:254:15: syntax error, unexpected matches, expecting IDENTIFIER-for-type
254 | case (st) matches
| ^~~~~~~
%Error: t/t_tagged_case.v:260:8: syntax error, unexpected '=', expecting '('
260 | st = tagged StrVal ("hello");
| ^
%Error: Exiting due to

16
test_regress/t/t_tagged_case.py Executable file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('simulator')
test.compile(fails=test.vlt_all, expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,306 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
// Test case pattern matching with tagged unions
// IEEE 1800-2023 Section 12.6.1
// Class for testing class references in tagged unions
class TestClass;
int value;
function new(int v);
value = v;
endfunction
endclass
`define stop $stop
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0x exp=%0x (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
module t;
// Basic tagged union (IEEE example)
typedef union tagged {
void Invalid;
int Valid;
} VInt;
// Tagged union with wide types
typedef union tagged packed {
void Invalid;
bit [8:1] Byte8NonZeroLSB; // Non-zero LSB
bit [0:31] Word32LittleEndian; // Opposite endianness
bit [59:0] Wide60; // 60-bit (33-64 special handling)
bit [89:0] Wide90; // 90-bit (64+ special handling)
} WideType;
// Tagged union with unpacked array
typedef union tagged {
void Invalid;
int Scalar;
int Arr[4]; // Unpacked array
} ArrayType;
// Tagged union with nested structure (IEEE example)
typedef union tagged {
struct {
bit [4:0] reg1, reg2, regd;
} Add;
union tagged {
bit [9:0] JmpU;
struct {
bit [1:0] cc;
bit [9:0] addr;
} JmpC;
} Jmp;
} Instr;
// Tagged union with chandle member
typedef union tagged {
void Invalid;
chandle Handle;
} ChandleType;
// Tagged union with class reference member
typedef union tagged {
void Invalid;
TestClass Obj;
} ClassType;
// Enum for testing enum members
typedef enum {RED, GREEN, BLUE} Color;
// Tagged union with real/shortreal members
typedef union tagged {
void Invalid;
real RealVal;
shortreal ShortRealVal;
} RealType;
// Tagged union with string member
typedef union tagged {
void Invalid;
string StrVal;
} StringType;
// Tagged union with enum member
typedef union tagged {
void Invalid;
Color ColorVal;
} EnumType;
`ifndef VCS
// Tagged union with event member
// Note: VCS incorrectly reports "the event data type is not allowed in structures and unions"
// but IEEE 1800-2023 does not prohibit this
typedef union tagged {
void Invalid;
event EvtVal;
} EventType;
`endif
VInt v;
WideType wt;
ArrayType at;
Instr instr;
ChandleType cht;
ClassType clt;
TestClass obj;
RealType rt;
StringType st;
EnumType et;
`ifndef VCS
EventType evt;
`endif
int result;
bit [59:0] wide60_result;
bit [89:0] wide90_result;
initial begin
// Test 1: Basic case matches with void tag
v = tagged Invalid;
result = 0;
case (v) matches
tagged Invalid : result = 1;
tagged Valid .n : result = n;
endcase
`checkh(result, 1);
// Test 2: Case matches with value binding
v = tagged Valid (123);
result = 0;
case (v) matches
tagged Invalid : result = -1;
tagged Valid .n : result = n;
endcase
`checkh(result, 123);
// Test 3: Wide type case matching - 60-bit
wt = tagged Wide60 (60'hFEDCBA987654321);
wide60_result = 0;
case (wt) matches
tagged Invalid : wide60_result = 0;
tagged Wide60 .w : wide60_result = w;
default : wide60_result = 0;
endcase
`checkh(wide60_result, 60'hFEDCBA987654321);
// Test 4: Wide type case matching - 90-bit
wt = tagged Wide90 (90'hDE_ADBEEFCA_FEBABE12_3456);
wide90_result = 0;
case (wt) matches
tagged Invalid : wide90_result = 0;
tagged Wide90 .w : wide90_result = w;
default : wide90_result = 0;
endcase
`checkh(wide90_result, 90'hDE_ADBEEFCA_FEBABE12_3456);
// Test 5: Non-zero LSB case match
wt = tagged Byte8NonZeroLSB (8'hA5);
result = 0;
case (wt) matches
tagged Byte8NonZeroLSB .b : result = b;
default : result = -1;
endcase
`checkh(result, 8'hA5);
// Test 6: Opposite endianness case match
wt = tagged Word32LittleEndian (32'hDEADBEEF);
result = 0;
case (wt) matches
tagged Word32LittleEndian .w : result = w;
default : result = -1;
endcase
`checkh(result, 32'hDEADBEEF);
// Test 7: Array type case matching
at = tagged Arr '{10, 20, 30, 40};
result = 0;
case (at) matches
tagged Invalid : result = -1;
tagged Scalar .s : result = s;
tagged Arr .a : result = a[0] + a[1] + a[2] + a[3];
endcase
`checkh(result, 100);
// Test 8: Nested tagged union case matching
instr = tagged Jmp (tagged JmpC '{2'd1, 10'd256});
result = 0;
case (instr) matches
tagged Add .* : result = -1;
tagged Jmp (tagged JmpU .a) : result = a;
tagged Jmp (tagged JmpC '{cc:.c, addr:.a}) : result = a;
endcase
`checkh(result, 256);
// Test 9: Chandle case matching (no binding - VCS limitation)
cht = tagged Invalid;
result = 0;
case (cht) matches
tagged Invalid : result = 1;
tagged Handle .* : result = 2; // Wildcard - can't bind chandle
endcase
`checkh(result, 1);
// Test 10: Class reference case matching
obj = new(42);
clt = tagged Obj (obj);
result = 0;
case (clt) matches
tagged Invalid : result = -1;
tagged Obj .o : result = o.value;
endcase
`checkh(result, 42);
// Test 11: Real member case matching
rt = tagged Invalid;
result = 0;
case (rt) matches
tagged Invalid : result = 1;
tagged RealVal .r : result = 2;
tagged ShortRealVal .r : result = 3;
endcase
`checkh(result, 1);
rt = tagged RealVal (3.14159);
result = 0;
case (rt) matches
tagged Invalid : result = -1;
tagged RealVal .r : begin
if (r == 3.14159) result = 1;
else result = 2;
end
tagged ShortRealVal .r : result = 3;
endcase
`checkh(result, 1);
// Test 12: Shortreal member case matching
rt = tagged ShortRealVal (2.5);
result = 0;
case (rt) matches
tagged Invalid : result = -1;
tagged RealVal .r : result = 2;
tagged ShortRealVal .r : begin
if (r == 2.5) result = 1;
else result = 3;
end
endcase
`checkh(result, 1);
// Test 13: String member case matching
st = tagged Invalid;
result = 0;
case (st) matches
tagged Invalid : result = 1;
tagged StrVal .s : result = 2;
endcase
`checkh(result, 1);
st = tagged StrVal ("hello");
result = 0;
case (st) matches
tagged Invalid : result = -1;
tagged StrVal .s : begin
if (s == "hello") result = 1;
else result = 2;
end
endcase
`checkh(result, 1);
// Test 14: Enum member case matching
et = tagged Invalid;
result = 0;
case (et) matches
tagged Invalid : result = 1;
tagged ColorVal .c : result = 2;
endcase
`checkh(result, 1);
et = tagged ColorVal (GREEN);
result = 0;
case (et) matches
tagged Invalid : result = -1;
tagged ColorVal .c : begin
if (c == GREEN) result = 1;
else result = 2;
end
endcase
`checkh(result, 1);
`ifndef VCS
// Test 15: Event member case matching
evt = tagged Invalid;
result = 0;
case (evt) matches
tagged Invalid : result = 1;
tagged EvtVal .* : result = 2;
endcase
`checkh(result, 1);
`endif
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,158 @@
%Error-UNSUPPORTED: t/t_tagged_if.v:24:17: Unsupported: tagged union
24 | typedef union tagged {
| ^~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_tagged_if.v:25:5: Unsupported: void (for tagged unions)
25 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:30:17: Unsupported: tagged union
30 | typedef union tagged packed {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:31:5: Unsupported: void (for tagged unions)
31 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:39:17: Unsupported: tagged union
39 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:40:5: Unsupported: void (for tagged unions)
40 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:46:17: Unsupported: tagged union
46 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:50:11: Unsupported: tagged union
50 | union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:60:17: Unsupported: tagged union
60 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:61:5: Unsupported: void (for tagged unions)
61 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:66:17: Unsupported: tagged union
66 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:67:5: Unsupported: void (for tagged unions)
67 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:75:17: Unsupported: tagged union
75 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:76:5: Unsupported: void (for tagged unions)
76 | void Invalid;
| ^~~~
%Warning-SHORTREAL: t/t_tagged_if.v:78:5: Unsupported: shortreal being promoted to real (suggest use real instead)
78 | shortreal ShortRealVal;
| ^~~~~~~~~
... For warning description see https://verilator.org/warn/SHORTREAL?v=latest
... Use "/* verilator lint_off SHORTREAL */" and lint_on around source to disable this message.
%Error-UNSUPPORTED: t/t_tagged_if.v:82:17: Unsupported: tagged union
82 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:83:5: Unsupported: void (for tagged unions)
83 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:88:17: Unsupported: tagged union
88 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:89:5: Unsupported: void (for tagged unions)
89 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:97:17: Unsupported: tagged union
97 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:98:5: Unsupported: void (for tagged unions)
98 | void Invalid;
| ^~~~
%Error: t/t_tagged_if.v:122:9: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
122 | v = tagged Invalid;
| ^~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: t/t_tagged_if.v:124:33: syntax error, unexpected ')', expecting '.' or tagged or .*
124 | if (v matches tagged Invalid)
| ^
%Error: t/t_tagged_if.v:131:9: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
131 | v = tagged Valid (42);
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:133:32: Unsupported: '{} tagged patterns
133 | if (v matches tagged Valid .n)
| ^
%Error-UNSUPPORTED: t/t_tagged_if.v:133:19: Unsupported: '{} tagged patterns
133 | if (v matches tagged Valid .n)
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:133:11: Unsupported: matches operator
133 | if (v matches tagged Valid .n)
| ^~~~~~~
%Error: t/t_tagged_if.v:140:9: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
140 | v = tagged Valid (100);
| ^~~~~~
%Error: t/t_tagged_if.v:142:33: syntax error, unexpected ')', expecting '.' or tagged or .*
142 | if (v matches tagged Invalid)
| ^
%Error: t/t_tagged_if.v:149:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
149 | wt = tagged Wide60 (60'hFEDCBA987654321);
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:151:34: Unsupported: '{} tagged patterns
151 | if (wt matches tagged Wide60 .w)
| ^
%Error-UNSUPPORTED: t/t_tagged_if.v:151:20: Unsupported: '{} tagged patterns
151 | if (wt matches tagged Wide60 .w)
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:151:12: Unsupported: matches operator
151 | if (wt matches tagged Wide60 .w)
| ^~~~~~~
%Error: t/t_tagged_if.v:158:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
158 | wt = tagged Wide90 (90'hDE_ADBEEFCA_FEBABE12_3456);
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:160:34: Unsupported: '{} tagged patterns
160 | if (wt matches tagged Wide90 .w)
| ^
%Error-UNSUPPORTED: t/t_tagged_if.v:160:20: Unsupported: '{} tagged patterns
160 | if (wt matches tagged Wide90 .w)
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:160:12: Unsupported: matches operator
160 | if (wt matches tagged Wide90 .w)
| ^~~~~~~
%Error: t/t_tagged_if.v:167:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
167 | wt = tagged Byte8NonZeroLSB (8'hA5);
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:169:43: Unsupported: '{} tagged patterns
169 | if (wt matches tagged Byte8NonZeroLSB .b)
| ^
%Error-UNSUPPORTED: t/t_tagged_if.v:169:20: Unsupported: '{} tagged patterns
169 | if (wt matches tagged Byte8NonZeroLSB .b)
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:169:12: Unsupported: matches operator
169 | if (wt matches tagged Byte8NonZeroLSB .b)
| ^~~~~~~
%Error: t/t_tagged_if.v:176:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
176 | wt = tagged Word32LittleEndian (32'hDEADBEEF);
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:178:46: Unsupported: '{} tagged patterns
178 | if (wt matches tagged Word32LittleEndian .w)
| ^
%Error-UNSUPPORTED: t/t_tagged_if.v:178:20: Unsupported: '{} tagged patterns
178 | if (wt matches tagged Word32LittleEndian .w)
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:178:12: Unsupported: matches operator
178 | if (wt matches tagged Word32LittleEndian .w)
| ^~~~~~~
%Error: t/t_tagged_if.v:185:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
185 | at = tagged Arr '{10, 20, 30, 40};
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:187:31: Unsupported: '{} tagged patterns
187 | if (at matches tagged Arr .a)
| ^
%Error-UNSUPPORTED: t/t_tagged_if.v:187:20: Unsupported: '{} tagged patterns
187 | if (at matches tagged Arr .a)
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:187:12: Unsupported: matches operator
187 | if (at matches tagged Arr .a)
| ^~~~~~~
%Error: t/t_tagged_if.v:194:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
194 | at = tagged Scalar (999);
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_if.v:196:34: Unsupported: '{} tagged patterns
196 | if (at matches tagged Scalar .s)
| ^
%Error: Exiting due to

16
test_regress/t/t_tagged_if.py Executable file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('simulator')
test.compile(fails=test.vlt_all, expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,412 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
// Test if pattern matching with tagged unions
// IEEE 1800-2023 Section 12.6.2
// Class for testing class references in tagged unions
class TestClass;
int value;
function new(int v);
value = v;
endfunction
endclass
`define stop $stop
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0x exp=%0x (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
module t;
// Basic tagged union (IEEE example)
typedef union tagged {
void Invalid;
int Valid;
} VInt;
// Tagged union with wide types
typedef union tagged packed {
void Invalid;
bit [8:1] Byte8NonZeroLSB; // Non-zero LSB
bit [0:31] Word32LittleEndian; // Opposite endianness
bit [59:0] Wide60; // 60-bit (33-64 special handling)
bit [89:0] Wide90; // 90-bit (64+ special handling)
} WideType;
// Tagged union with unpacked array
typedef union tagged {
void Invalid;
int Scalar;
int Arr[4]; // Unpacked array
} ArrayType;
// Tagged union with nested structure
typedef union tagged {
struct {
bit [4:0] reg1, reg2, regd;
} Add;
union tagged {
bit [9:0] JmpU;
struct {
bit [1:0] cc;
bit [9:0] addr;
} JmpC;
} Jmp;
} Instr;
// Tagged union with chandle member
typedef union tagged {
void Invalid;
chandle Handle;
} ChandleType;
// Tagged union with class reference member
typedef union tagged {
void Invalid;
TestClass Obj;
} ClassType;
// Enum for testing enum members
typedef enum {RED, GREEN, BLUE} Color;
// Tagged union with real/shortreal members
typedef union tagged {
void Invalid;
real RealVal;
shortreal ShortRealVal;
} RealType;
// Tagged union with string member
typedef union tagged {
void Invalid;
string StrVal;
} StringType;
// Tagged union with enum member
typedef union tagged {
void Invalid;
Color ColorVal;
} EnumType;
`ifndef VCS
// Tagged union with event member
// Note: VCS incorrectly reports "the event data type is not allowed in structures and unions"
// but IEEE 1800-2023 does not prohibit this
typedef union tagged {
void Invalid;
event EvtVal;
} EventType;
`endif
VInt v;
WideType wt;
ArrayType at;
Instr instr;
ChandleType cht;
ClassType clt;
TestClass obj;
RealType rt;
StringType st;
EnumType et;
`ifndef VCS
EventType evt;
`endif
int result;
bit [59:0] wide60_result;
bit [89:0] wide90_result;
initial begin
// Test 1: Basic if matches - void tag
v = tagged Invalid;
result = 0;
if (v matches tagged Invalid)
result = 1;
else
result = 2;
`checkh(result, 1);
// Test 2: Basic if matches - value with binding
v = tagged Valid (42);
result = 0;
if (v matches tagged Valid .n)
result = n;
else
result = -1;
`checkh(result, 42);
// Test 3: if-else chain
v = tagged Valid (100);
result = 0;
if (v matches tagged Invalid)
result = 1;
else if (v matches tagged Valid .n)
result = n;
`checkh(result, 100);
// Test 4: Wide type if matching - 60-bit
wt = tagged Wide60 (60'hFEDCBA987654321);
wide60_result = 0;
if (wt matches tagged Wide60 .w)
wide60_result = w;
else
wide60_result = 0;
`checkh(wide60_result, 60'hFEDCBA987654321);
// Test 5: Wide type if matching - 90-bit
wt = tagged Wide90 (90'hDE_ADBEEFCA_FEBABE12_3456);
wide90_result = 0;
if (wt matches tagged Wide90 .w)
wide90_result = w;
else
wide90_result = 0;
`checkh(wide90_result, 90'hDE_ADBEEFCA_FEBABE12_3456);
// Test 6: Non-zero LSB if match
wt = tagged Byte8NonZeroLSB (8'hA5);
result = 0;
if (wt matches tagged Byte8NonZeroLSB .b)
result = b;
else
result = -1;
`checkh(result, 8'hA5);
// Test 7: Opposite endianness if match
wt = tagged Word32LittleEndian (32'hDEADBEEF);
result = 0;
if (wt matches tagged Word32LittleEndian .w)
result = w;
else
result = -1;
`checkh(result, 32'hDEADBEEF);
// Test 8: Array type if matching
at = tagged Arr '{10, 20, 30, 40};
result = 0;
if (at matches tagged Arr .a)
result = a[0] + a[1] + a[2] + a[3];
else
result = -1;
`checkh(result, 100);
// Test 9: Array type scalar if match
at = tagged Scalar (999);
result = 0;
if (at matches tagged Scalar .s)
result = s;
else
result = -1;
`checkh(result, 999);
// Test 10: Nested pattern matching (IEEE example)
instr = tagged Jmp (tagged JmpC '{2'd1, 10'd256});
result = 0;
if (instr matches tagged Jmp (tagged JmpC '{cc:.c, addr:.a}))
result = a; // 'a' is bound in pattern
else
result = -1;
`checkh(result, 256);
// Test 11: Chained matches with &&& (IEEE example)
instr = tagged Jmp (tagged JmpC '{2'd2, 10'd128});
result = 0;
if (instr matches tagged Jmp .j &&&
j matches tagged JmpC '{cc:.c, addr:.a})
result = a; // 'a' bound from second pattern
else
result = -1;
`checkh(result, 128);
// Test 12: Pattern with boolean filter expression
v = tagged Valid (75);
result = 0;
if (v matches tagged Valid .n &&& (n > 50))
result = 1;
else
result = 2;
`checkh(result, 1);
// Test 13: Pattern with boolean filter - no match
v = tagged Valid (25);
result = 0;
if (v matches tagged Valid .n &&& (n > 50))
result = 1;
else
result = 2;
`checkh(result, 2);
// Test 14: Scope test - bound variable only in true branch
v = tagged Valid (99);
result = 0;
if (v matches tagged Valid .x) begin
result = x; // x is in scope here
end
// x is NOT in scope here (else branch / after)
`checkh(result, 99);
// Test 15: Add instruction matching
instr = tagged Add '{5'd10, 5'd20, 5'd30};
result = 0;
if (instr matches tagged Add '{.r1, .r2, .rd})
result = r1 + r2 + rd;
else
result = -1;
`checkh(result, 60);
// Test 16: Complex filter with register file simulation
instr = tagged Jmp (tagged JmpC '{2'd3, 10'd100});
result = 0;
// If conditional jump and condition register is non-zero
// Use nested if for boolean filter (VCS limitation with &&& after chained matches)
if (instr matches tagged Jmp .j &&&
j matches tagged JmpC '{cc:.c, addr:.a}) begin
if (c != 0)
result = a;
else
result = -1;
end else
result = -1;
`checkh(result, 100);
// Test 17: Unconditional jump matching
instr = tagged Jmp (tagged JmpU 10'd512);
result = 0;
if (instr matches tagged Jmp (tagged JmpU .a))
result = a;
else
result = -1;
`checkh(result, 512);
// Test 18: Wildcard pattern in if
instr = tagged Add '{5'd1, 5'd2, 5'd3};
result = 0;
if (instr matches tagged Add .*)
result = 1;
else if (instr matches tagged Jmp .*)
result = 2;
`checkh(result, 1);
// Test 19: Chandle member if matching
cht = tagged Invalid;
result = 0;
if (cht matches tagged Invalid)
result = 1;
else
result = 2;
`checkh(result, 1);
cht = tagged Handle (null);
result = 0;
if (cht matches tagged Handle .*) // Wildcard - VCS can't bind chandle
result = 1;
else
result = 2;
`checkh(result, 1);
// Test 20: Class reference member if matching
obj = new(42);
clt = tagged Invalid;
result = 0;
if (clt matches tagged Invalid)
result = 1;
else
result = 2;
`checkh(result, 1);
clt = tagged Obj (obj);
result = 0;
if (clt matches tagged Obj .o)
result = o.value;
else
result = -1;
`checkh(result, 42);
// Test 21: Real member if matching
rt = tagged Invalid;
result = 0;
if (rt matches tagged Invalid)
result = 1;
else
result = 2;
`checkh(result, 1);
rt = tagged RealVal (3.14159);
result = 0;
if (rt matches tagged RealVal .r) begin
if (r == 3.14159)
result = 1;
else
result = 2;
end else
result = -1;
`checkh(result, 1);
// Test 22: Shortreal member if matching
rt = tagged ShortRealVal (2.5);
result = 0;
if (rt matches tagged ShortRealVal .r) begin
if (r == 2.5)
result = 1;
else
result = 2;
end else
result = -1;
`checkh(result, 1);
// Test 23: String member if matching
st = tagged Invalid;
result = 0;
if (st matches tagged Invalid)
result = 1;
else
result = 2;
`checkh(result, 1);
st = tagged StrVal ("hello");
result = 0;
if (st matches tagged StrVal .s) begin
if (s == "hello")
result = 1;
else
result = 2;
end else
result = -1;
`checkh(result, 1);
// Test 24: Enum member if matching
et = tagged Invalid;
result = 0;
if (et matches tagged Invalid)
result = 1;
else
result = 2;
`checkh(result, 1);
et = tagged ColorVal (GREEN);
result = 0;
if (et matches tagged ColorVal .c) begin
if (c == GREEN)
result = 1;
else
result = 2;
end else
result = -1;
`checkh(result, 1);
`ifndef VCS
// Test 25: Event member if matching
evt = tagged Invalid;
result = 0;
if (evt matches tagged Invalid)
result = 1;
else
result = 2;
`checkh(result, 1);
`endif
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,158 @@
%Error-UNSUPPORTED: t/t_tagged_union.v:24:17: Unsupported: tagged union
24 | typedef union tagged {
| ^~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_tagged_union.v:25:5: Unsupported: void (for tagged unions)
25 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_union.v:31:17: Unsupported: tagged union
31 | typedef union tagged packed {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_union.v:32:5: Unsupported: void (for tagged unions)
32 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_union.v:52:17: Unsupported: tagged union
52 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_union.v:53:5: Unsupported: void (for tagged unions)
53 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_union.v:60:17: Unsupported: tagged union
60 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_union.v:64:11: Unsupported: tagged union
64 | union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_union.v:74:17: Unsupported: tagged union
74 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_union.v:75:5: Unsupported: void (for tagged unions)
75 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_union.v:80:17: Unsupported: tagged union
80 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_union.v:81:5: Unsupported: void (for tagged unions)
81 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_union.v:89:17: Unsupported: tagged union
89 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_union.v:90:5: Unsupported: void (for tagged unions)
90 | void Invalid;
| ^~~~
%Warning-SHORTREAL: t/t_tagged_union.v:92:5: Unsupported: shortreal being promoted to real (suggest use real instead)
92 | shortreal ShortRealVal;
| ^~~~~~~~~
... For warning description see https://verilator.org/warn/SHORTREAL?v=latest
... Use "/* verilator lint_off SHORTREAL */" and lint_on around source to disable this message.
%Error-UNSUPPORTED: t/t_tagged_union.v:96:17: Unsupported: tagged union
96 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_union.v:97:5: Unsupported: void (for tagged unions)
97 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_union.v:102:17: Unsupported: tagged union
102 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_union.v:103:5: Unsupported: void (for tagged unions)
103 | void Invalid;
| ^~~~
%Error-UNSUPPORTED: t/t_tagged_union.v:111:17: Unsupported: tagged union
111 | typedef union tagged {
| ^~~~~~
%Error-UNSUPPORTED: t/t_tagged_union.v:112:5: Unsupported: void (for tagged unions)
112 | void Invalid;
| ^~~~
%Error: t/t_tagged_union.v:133:11: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
133 | vi1 = tagged Invalid;
| ^~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: t/t_tagged_union.v:134:11: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
134 | vi2 = tagged Invalid;
| ^~~~~~
%Error: t/t_tagged_union.v:137:11: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
137 | vi1 = tagged Valid (42);
| ^~~~~~
%Error: t/t_tagged_union.v:140:11: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
140 | vi2 = tagged Valid (23 + 34);
| ^~~~~~
%Error: t/t_tagged_union.v:144:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
144 | mt = tagged Invalid;
| ^~~~~~
%Error: t/t_tagged_union.v:146:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
146 | mt = tagged IntVal (32'h12345678);
| ^~~~~~
%Error: t/t_tagged_union.v:149:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
149 | mt = tagged ShortVal (16'hABCD);
| ^~~~~~
%Error: t/t_tagged_union.v:152:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
152 | mt = tagged ByteVal (8'h5A);
| ^~~~~~
%Error: t/t_tagged_union.v:155:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
155 | mt = tagged BitVal (1'b1);
| ^~~~~~
%Error: t/t_tagged_union.v:159:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
159 | mt = tagged Byte8NonZeroLSB (8'hA5);
| ^~~~~~
%Error: t/t_tagged_union.v:162:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
162 | mt = tagged Word16NonZeroLSB (16'h1234);
| ^~~~~~
%Error: t/t_tagged_union.v:166:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
166 | mt = tagged Word32LittleEndian (32'hDEADBEEF);
| ^~~~~~
%Error: t/t_tagged_union.v:169:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
169 | mt = tagged Word16LittleEndian (16'hCAFE);
| ^~~~~~
%Error: t/t_tagged_union.v:173:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
173 | mt = tagged Wide60 (60'hFEDCBA987654321);
| ^~~~~~
%Error: t/t_tagged_union.v:176:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
176 | mt = tagged Wide60NonZeroLSB (60'h123456789ABCDEF);
| ^~~~~~
%Error: t/t_tagged_union.v:179:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
179 | mt = tagged Wide60LittleEndian (60'hABCDEF012345678);
| ^~~~~~
%Error: t/t_tagged_union.v:183:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
183 | mt = tagged Wide90 (90'hFF_FFFFFFFF_FFFFFFFF_FFFF);
| ^~~~~~
%Error: t/t_tagged_union.v:186:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
186 | mt = tagged Wide90NonZeroLSB (90'hDE_ADBEEFCA_FEBABE12_3456);
| ^~~~~~
%Error: t/t_tagged_union.v:189:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
189 | mt = tagged Wide90LittleEndian (90'h11_11111122_22222233_3333);
| ^~~~~~
%Error: t/t_tagged_union.v:193:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
193 | at = tagged Invalid;
| ^~~~~~
%Error: t/t_tagged_union.v:195:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
195 | at = tagged Scalar (999);
| ^~~~~~
%Error: t/t_tagged_union.v:198:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
198 | at = tagged UnpackedArr '{100, 200, 300, 400};
| ^~~~~~
%Error: t/t_tagged_union.v:204:10: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
204 | at = tagged UnpackedArr2D '{'{32'hA, 32'hB, 32'hC}, '{32'hD, 32'hE, 32'hF}};
| ^~~~~~
%Error: t/t_tagged_union.v:213:13: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
213 | instr = tagged Add '{5'd1, 5'd2, 5'd3};
| ^~~~~~
%Error: t/t_tagged_union.v:219:13: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
219 | instr = tagged Add '{reg2:5'd10, regd:5'd20, reg1:5'd5};
| ^~~~~~
%Error: t/t_tagged_union.v:225:13: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
225 | instr = tagged Jmp (tagged JmpU 10'd512);
| ^~~~~~
%Error: t/t_tagged_union.v:229:13: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
229 | instr = tagged Jmp (tagged JmpC '{2'd1, 10'd256});
| ^~~~~~
%Error: t/t_tagged_union.v:234:13: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
234 | instr = tagged Jmp (tagged JmpC '{cc:2'd3, addr:10'd100});
| ^~~~~~
%Error: t/t_tagged_union.v:239:11: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
239 | cht = tagged Invalid;
| ^~~~~~
%Error: t/t_tagged_union.v:240:11: syntax error, unexpected tagged, expecting IDENTIFIER-for-type
240 | cht = tagged Handle (null);
| ^~~~~~
%Error: Exiting due to

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('simulator')
test.compile(fails=test.vlt_all, expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,276 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
// Test tagged union declaration, expressions, and member access
// IEEE 1800-2023 Sections 7.3.2, 11.9
// Class for testing class references in tagged unions
class TestClass;
int value;
function new(int v);
value = v;
endfunction
endclass
`define stop $stop
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0x exp=%0x (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
module t;
// Basic tagged union with void and int (IEEE example)
typedef union tagged {
void Invalid;
int Valid;
} VInt;
// Tagged union with multiple data types including wide types
// Tests: non-zero LSBs, 60-bit (33-64 range), 90-bit (64+ range), opposite endianness
typedef union tagged packed {
void Invalid;
int IntVal;
shortint ShortVal;
longint LongVal;
byte ByteVal;
bit BitVal;
logic LogicVal;
bit [8:1] Byte8NonZeroLSB; // Non-zero LSB
bit [16:1] Word16NonZeroLSB; // Non-zero LSB
bit [0:31] Word32LittleEndian; // Opposite endianness
bit [0:15] Word16LittleEndian; // Opposite endianness
bit [59:0] Wide60; // 60-bit (33-64 special handling)
bit [89:0] Wide90; // 90-bit (64+ special handling)
bit [63:4] Wide60NonZeroLSB; // 60-bit with non-zero LSB
bit [99:10] Wide90NonZeroLSB; // 90-bit with non-zero LSB
bit [0:59] Wide60LittleEndian; // 60-bit opposite endianness
bit [0:89] Wide90LittleEndian; // 90-bit opposite endianness
} MultiType;
// Tagged union with unpacked array members
typedef union tagged {
void Invalid;
int Scalar;
int UnpackedArr[4]; // Unpacked array
bit [31:0] UnpackedArr2D[2][3]; // 2D unpacked array
} ArrayType;
// Tagged union with nested struct (IEEE example)
typedef union tagged {
struct {
bit [4:0] reg1, reg2, regd;
} Add;
union tagged {
bit [9:0] JmpU;
struct {
bit [1:0] cc;
bit [9:0] addr;
} JmpC;
} Jmp;
} Instr;
// Tagged union with chandle member
typedef union tagged {
void Invalid;
chandle Handle;
} ChandleType;
// Tagged union with class reference member
typedef union tagged {
void Invalid;
TestClass Obj;
} ClassType;
// Enum for testing enum members
typedef enum {RED, GREEN, BLUE} Color;
// Tagged union with real/shortreal members
typedef union tagged {
void Invalid;
real RealVal;
shortreal ShortRealVal;
} RealType;
// Tagged union with string member
typedef union tagged {
void Invalid;
string StrVal;
} StringType;
// Tagged union with enum member
typedef union tagged {
void Invalid;
Color ColorVal;
} EnumType;
`ifndef VCS
// Tagged union with event member
// Note: VCS incorrectly reports "the event data type is not allowed in structures and unions"
// but IEEE 1800-2023 does not prohibit this
typedef union tagged {
void Invalid;
event EvtVal;
} EventType;
`endif
VInt vi1, vi2;
MultiType mt;
ArrayType at;
Instr instr;
ChandleType cht;
ClassType clt;
TestClass obj;
RealType rt;
StringType st;
EnumType et;
`ifndef VCS
EventType evt;
`endif
initial begin
// Test 1: Basic void member
vi1 = tagged Invalid;
vi2 = tagged Invalid;
// Test 2: Basic value member
vi1 = tagged Valid (42);
`checkh(vi1.Valid, 42);
vi2 = tagged Valid (23 + 34);
`checkh(vi2.Valid, 57);
// Test 3: MultiType with various data types
mt = tagged Invalid;
mt = tagged IntVal (32'h12345678);
`checkh(mt.IntVal, 32'h12345678);
mt = tagged ShortVal (16'hABCD);
`checkh(mt.ShortVal, 16'hABCD);
mt = tagged ByteVal (8'h5A);
`checkh(mt.ByteVal, 8'h5A);
mt = tagged BitVal (1'b1);
`checkh(mt.BitVal, 1'b1);
// Test 4: Non-zero LSB types
mt = tagged Byte8NonZeroLSB (8'hA5);
`checkh(mt.Byte8NonZeroLSB, 8'hA5);
mt = tagged Word16NonZeroLSB (16'h1234);
`checkh(mt.Word16NonZeroLSB, 16'h1234);
// Test 5: Opposite endianness (little-endian style ranges)
mt = tagged Word32LittleEndian (32'hDEADBEEF);
`checkh(mt.Word32LittleEndian, 32'hDEADBEEF);
mt = tagged Word16LittleEndian (16'hCAFE);
`checkh(mt.Word16LittleEndian, 16'hCAFE);
// Test 6: Wide types (60-bit, in 33-64 range)
mt = tagged Wide60 (60'hFEDCBA987654321);
`checkh(mt.Wide60, 60'hFEDCBA987654321);
mt = tagged Wide60NonZeroLSB (60'h123456789ABCDEF);
`checkh(mt.Wide60NonZeroLSB, 60'h123456789ABCDEF);
mt = tagged Wide60LittleEndian (60'hABCDEF012345678);
`checkh(mt.Wide60LittleEndian, 60'hABCDEF012345678);
// Test 7: Wide types (90-bit, in 64+ range)
mt = tagged Wide90 (90'hFF_FFFFFFFF_FFFFFFFF_FFFF);
`checkh(mt.Wide90, 90'hFF_FFFFFFFF_FFFFFFFF_FFFF);
mt = tagged Wide90NonZeroLSB (90'hDE_ADBEEFCA_FEBABE12_3456);
`checkh(mt.Wide90NonZeroLSB, 90'hDE_ADBEEFCA_FEBABE12_3456);
mt = tagged Wide90LittleEndian (90'h11_11111122_22222233_3333);
`checkh(mt.Wide90LittleEndian, 90'h11_11111122_22222233_3333);
// Test 8: Unpacked array members
at = tagged Invalid;
at = tagged Scalar (999);
`checkh(at.Scalar, 999);
at = tagged UnpackedArr '{100, 200, 300, 400};
`checkh(at.UnpackedArr[0], 100);
`checkh(at.UnpackedArr[1], 200);
`checkh(at.UnpackedArr[2], 300);
`checkh(at.UnpackedArr[3], 400);
at = tagged UnpackedArr2D '{'{32'hA, 32'hB, 32'hC}, '{32'hD, 32'hE, 32'hF}};
`checkh(at.UnpackedArr2D[0][0], 32'hA);
`checkh(at.UnpackedArr2D[0][1], 32'hB);
`checkh(at.UnpackedArr2D[0][2], 32'hC);
`checkh(at.UnpackedArr2D[1][0], 32'hD);
`checkh(at.UnpackedArr2D[1][1], 32'hE);
`checkh(at.UnpackedArr2D[1][2], 32'hF);
// Test 9: Nested tagged union (Instr example from IEEE)
instr = tagged Add '{5'd1, 5'd2, 5'd3};
`checkh(instr.Add.reg1, 5'd1);
`checkh(instr.Add.reg2, 5'd2);
`checkh(instr.Add.regd, 5'd3);
// Create Add with named struct fields
instr = tagged Add '{reg2:5'd10, regd:5'd20, reg1:5'd5};
`checkh(instr.Add.reg1, 5'd5);
`checkh(instr.Add.reg2, 5'd10);
`checkh(instr.Add.regd, 5'd20);
// Test 10: Nested tagged union - unconditional jump
instr = tagged Jmp (tagged JmpU 10'd512);
`checkh(instr.Jmp.JmpU, 10'd512);
// Test 11: Nested tagged union - conditional jump
instr = tagged Jmp (tagged JmpC '{2'd1, 10'd256});
`checkh(instr.Jmp.JmpC.cc, 2'd1);
`checkh(instr.Jmp.JmpC.addr, 10'd256);
// Test 12: Nested tagged union - conditional jump with named fields
instr = tagged Jmp (tagged JmpC '{cc:2'd3, addr:10'd100});
`checkh(instr.Jmp.JmpC.cc, 2'd3);
`checkh(instr.Jmp.JmpC.addr, 10'd100);
// Test 13: Chandle member
cht = tagged Invalid;
cht = tagged Handle (null);
// Test 14: Class reference member
obj = new(42);
clt = tagged Invalid;
clt = tagged Obj (obj);
`checkh(clt.Obj.value, 42);
// Test 15: Real member
rt = tagged Invalid;
rt = tagged RealVal (3.14159);
if (rt.RealVal != 3.14159) $stop;
// Test 16: Shortreal member
rt = tagged ShortRealVal (2.5);
if (rt.ShortRealVal != 2.5) $stop;
// Test 17: String member
st = tagged Invalid;
st = tagged StrVal ("hello");
if (st.StrVal != "hello") $stop;
// Test 18: Enum member
et = tagged Invalid;
et = tagged ColorVal (GREEN);
if (et.ColorVal != GREEN) $stop;
`ifndef VCS
// Test 19: Event member
evt = tagged Invalid;
`endif
$write("*-* All Finished *-*\n");
$finish;
end
endmodule