Tagged union expressions

A tagged union expression (packed or unpacked) is expressed using the keyword tagged followed by a tagged union member identifier, followed by an expression representing the corresponding member value. For void members, the member value expression is omitted. For Example:

typedef union tagged {
void Invalid;
int Valid;
} VInt;
VInt vi1, vi2;
vi1 = tagged Valid (23+34); // Create Valid int
vi2 = tagged Invalid; // Create an Invalid value

In the tagged union expressions below, the expressions in braces are structure expressions.

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;
Instr i1, i2; // Create an Add instruction with its 3 register fields
i1 = ( e ? tagged Add { e1, 4, ed }; // struct members by position
: tagged Add { reg2:e2, regd:3, reg1:19 }); // by name (order irrelevant)
// Create a Jump instruction, with "unconditional" sub-opcode
i1 = tagged Jmp (tagged JmpU 239);
// Create a Jump instruction, with "conditional" sub-opcode
i2 = tagged Jmp (tagged JmpC { 2, 83 }); // inner struct by position
i2 = tagged Jmp (tagged JmpC { cc:2, addr:83 }); // by name

The type of a tagged union expression must be known from its context (e.g., it is used in the right-hand side of an assignment to a variable whose type is known, or it is has a cast, or it is used inside another expression from which its type is known). The expression evaluates to a tagged union value of that type. The tagged union expression can be completely type-checked statically: the only member names allowed after the tagged keyword are the member names for the expression type, and the member expression must have the corresponding member type.

An uninitialized variable of tagged union type shall be undefined. This includes the tag bits. A variable of tagged union type can be initialized with a tagged union expression provided the member value expression is a legal initializer for the member type.

Members of tagged unions can be read or assigned using the usual dot notation. Such accesses are completely type-checked, i.e., the value read or assigned must be consistent with the current tag. In general, this can require a runtime check. An attempt to read or assign a value whose type is inconsistent with the tag results in a runtime error.

All the following examples are legal only if the instruction variable instr currently has the tag Add:

x = i1.Add.reg1;
i1.Add = {19, 4, 3};
i1.Add.reg2 = 4;

<< Previous | Next >>

Structure expressions

A structure expression (packed or unpacked) can be built from member expressions using braces and commas, with the members in declaration order. Replicate operators can be used to set the values for the exact number of members. Each member expression shall be evaluated in the context of an assignment to the type of the corresponding member in the structure. It can also be built with the names of the members.

module mod1;
typedef struct {
int x;
int y;
} st;
st s1;
int k = 1;
initial begin
#1 s1 = {1, 2+k}; // by position
#1 $display( s1.x, s1.y);
#1 s1 = {x:2, y:3+k); // by name
#1 $display( s1);
#1 $finish;
end
endmodule

It can sometimes be useful to set structure members to a value without having to keep track of how many members there are, or what the names are. This can be done with the default keyword:

initial s1 = {default:2}; // sets x and y to 2

The {member:value} or {data_type: default_value} syntax can also be used:

ab abkey[1:0] = {{a:1, b:1.0}, {int:2, shortreal:2.0}};

Note that the default keyword applies to members in nested structures or elements in unpacked arrays in structures. It descends the nesting to a built-in type or a packed array of them.

struct {
int A;
struct {
int B, C;
} BC1, BC2;
}
ABC = {A:1, BC1:{B:2, C:3}, BC2:{B:4,C:5}};
DEF = {default:10};

To deal with the problem of members of different types, a type can be used as the key. This overrides the
default for members of that type:

typedef struct {
logic [7:0] a;
bit b;
bit signed [31:0] c;
string s;
} sa;
sa s2;
initial s2 = {int:1, default:0, string:""}; // set all to 0 except the array of bits to 1 and string to ""

Similarly, an individual member can be set to override the general default and the type default:

initial #10 s1 = {default:’1, s : ""}; // set all to 1 except s to ""

SystemVerilog determines the context of the braces when used in the context of an assignment. If used in the context of an assignment to an unpacked structure, the braces represent an unpacked structure literal or expression. Outside the context of an assignment to an aggregate type, an explicit cast must be used with the braces to distinguish it from a concatenation. When the braces include a label, type, or default key, the braces shall not be interpreted as a concatenation for both packed and unpacked structure types.

The matching rules are as follows:

  • A member:value: specifies an explicit value for a named member of the structure. The named member must be at the top level of the structure—a member with the same name in some level of substructure shall not be set. The value must be castable to the member type and is evaluated in the context of an assignment to the named member, otherwise, an error is generated.
  • The type:value specifies an explicit value for a field in the structure that is equivalent to the type and has not been set by a field name key above. If the same type key is mentioned more than once, the last value is used. The value is evaluated in the context of an assignment to the matching type.
  • The default:value applies to members that are not matched by either member name or type key and are not either structures or unpacked arrays. The value is evaluated in the context of each assignment to a member by default and must be castable to the member type, otherwise an error is generated. For unmatched structure members, the type and default specifiers are applied recursively according to the rules in this section to each member of the substructure. For unmatched unpacked array members, the type and default keys are applied to the array according to the rules for unpacked arrays. Every member must be covered by one of these rules. If the type key, default key, or replication operator is used on an expression with side effects, the number of times that expression evaluates is undefined.

<< Previous | Next >>