• 沒有找到結果。

Unified Hardware Design, Specification, and Verification Language

6. Data types

6.22 Type compatibility

Some constructs and operations require a certain level of type compatibility for their operands to be legal.

There are five levels of type compatibility, formally defined here: matching, equivalent, assignment compatible, cast compatible, and nonequivalent.

SystemVerilog does not require a category for identical types to be defined here because there is no construct in the SystemVerilog language that requires it. For example, as defined below, int can be interchanged with bitsigned [31:0] wherever it is syntactically legal to do so. Users can define their own level of type identity by using the $typename system function (see 20.6.1) or through use of the PLI.

The scope of a data type identifier shall include the hierarchical instance scope. In other words, each instance with a user-defined type declared inside the instance creates a unique type. To have type matching or equivalence among multiple instances of the same module, interface, program, or checker, a class, enum, unpacked structure, or unpacked union type must be declared at a higher level in the compilation-unit scope than the declaration of the module, interface, program, or checker, or imported from a package. For type matching, this is true even for packed structure and packed union types.

6.22.1 Matching types

Two data types shall be defined as matching data types using the following inductive definition. If two data types do not match using the following definition, then they shall be defined to be nonmatching.

a) Any built-in type matches every other occurrence of itself, in every scope.

b) A simple typedef or type parameter override that renames a built-in or user-defined type matches that built-in or user-defined type within the scope of the type identifier.

typedef bit node; // 'bit' and 'node' are matching types typedef type1 type2; // 'type1' and 'type2' are matching types

c) An anonymous enum, struct, or union type matches itself among data objects declared within the same declaration statement and no other data types.

struct packed {int A; int B;} AB1, AB2; // AB1, AB2 have matching types struct packed {int A; int B;} AB3; // the type of AB3 does not match

// the type of AB1

d) A typedef for an enum, struct, union, or class matches itself and the type of data objects declared using that data type within the scope of the data type identifier.

typedef struct packed {int A; int B;} AB_t;

AB_t AB1; AB_t AB2; // AB1 and AB2 have matching types

typedef struct packed {int A; int B;} otherAB_t;

otherAB_t AB3; // the type of AB3 does not match the type of AB1 or AB2 e) A simple bit vector type that does not have a predefined width and one that does have a predefined width match if both are 2-state or both are 4-state, both are signed or both are unsigned, both have the same width, and the range of the simple bit vector type without a predefined width is [width–

1:0].

typedef bit signed [7:0] BYTE; // matches the byte type

typedef bit signed [0:7] ETYB; // does not match the byte type

f) Two array types match if they are both packed or both unpacked, are the same kind of array (fixed-size, dynamic, associative, or queue), have matching index types (for associative arrays), and have matching element types. Fixed-size arrays shall also have the same left and right range bounds. Note that the element type of a multidimensional array is itself an array type.

typedef byte MEM_BYTES [256];

typedef bit signed [7:0] MY_MEM_BYTES [256]; // MY_MEM_BYTES matches // MEM_BYTES

typedef logic [1:0] [3:0] NIBBLES;

typedef logic [7:0] MY_BYTE; // MY_BYTE and NIBBLES are not matching types typedef logic MD_ARY [][2:0];

typedef logic MD_ARY_TOO [][0:2]; // Does not match MD_ARY

g) Explicitly adding signed or unsigned modifiers to a type that does not change its default signing creates a type that matches the type without the explicit signing specification.

typedef byte signed MY_CHAR; // MY_CHAR matches the byte type

h) A typedef for an enum, struct, union, or class type declared in a package always matches itself, regardless of the scope into which the type is imported.

6.22.2 Equivalent types

Two data types shall be defined as equivalent data types using the following inductive definition. If the two data types are not defined as equivalent using the following definition, then they shall be defined to be nonequivalent.

a) If two types match, they are equivalent.

b) An anonymous enum, unpacked struct, or unpacked union type is equivalent to itself among data objects declared within the same declaration statement and no other data types.

struct {int A; int B;} AB1, AB2; // AB1, AB2 have equivalent types struct {int A; int B;} AB3; // AB3 is not type equivalent to AB1 c) Packed arrays, packed structures, packed unions, and built-in integral types are equivalent if they

contain the same number of total bits, are either all 2-state or all 4-state, and are either all signed or all unsigned.

NOTE—If any bit of a packed structure or union is 4-state, the entire structure or union is considered 4-state.

typedef bit signed [7:0] BYTE; // equivalent to the byte type typedef struct packed signed {bit[3:0] a, b;} uint8;

// equivalent to the byte type

VERIFICATION LANGUAGE

d) Unpacked fixed-size array types are equivalent if they have equivalent element types and equal size;

the actual range bounds may differ. Note that the element type of a multidimensional array is itself an array type.

bit [9:0] A [0:5];

bit [1:10] B [6];

typedef bit [10:1] uint10;

uint10 C [6:1]; // A, B and C have equivalent types typedef int anint [0:0]; // anint is not type equivalent to int e) Dynamic array, associative array, and queue types are equivalent if they are the same kind of array

(dynamic, associative, or queue), have equivalent index types (for associative arrays), and have equivalent element types.

The following example is assumed to be within one compilation unit, although the package declaration need not be in the same unit:

package p1;

typedef struct {int A;} t_1;

endpackage

typedef struct {int A;} t_2;

module sub();

import p1::t_1;

parameter type t_3 = int;

parameter type t_4 = int;

typedef struct {int A;} t_5;

t_1 v1; t_2 v2; t_3 v3; t_4 v4; t_5 v5;

endmodule module top();

typedef struct {int A;} t_6;

sub #(.t_3(t_6)) s1 ();

sub #(.t_3(t_6)) s2 ();

initial begin

s1.v1 = s2.v1; // legal - both types from package p1 (rule 8) s1.v2 = s2.v2; // legal - both types from $unit (rule 4) s1.v3 = s2.v3; // legal - both types from top (rule 2) s1.v4 = s2.v4; // legal - both types are int (rule 1) s1.v5 = s2.v5; // illegal - types from s1 and s2 (rule 4) end

endmodule

6.22.3 Assignment compatible

All equivalent types, and all nonequivalent types that have implicit casting rules defined between them, are assignment-compatible types. For example, all integral types are assignment compatible. Conversion between assignment-compatible types can involve loss of data by truncation or rounding.

Unpacked arrays are assignment compatible with certain other arrays that are not of equivalent type.

Assignment compatibility of unpacked arrays is discussed in detail in 7.6.

Compatibility can be in one direction only. For example, an enum can be converted to an integral type without a cast, but not the other way around. Implicit casting rules are defined in 6.24.

6.22.4 Cast compatible

All assignment-compatible types, plus all nonequivalent types that have defined explicit casting rules, are cast-compatible types. For example, an integral type requires a cast to be assigned to an enum.

Explicit casting rules are defined in 6.24.

6.22.5 Type incompatible

Type incompatible includes all the remaining nonequivalent types that have no defined implicit or explicit casting rules. Class handles, interface class handles, and chandles are type incompatible with all other types.

6.22.6 Matching nettypes

a) A nettype matches itself and the nettype of nets declared using that nettype within the scope of the nettype type identifier.

b) A simple nettype that renames a user-defined nettype matches that user-defined nettype within the scope of the nettype identifier.

// declare another name nettypeid2 for nettype nettypeid1 nettype nettypeid1 nettypeid2;