Section 11.2

LRM-58

Change Syntax 11-1 (change in red):

class_declaration ::=

{ attribute_instance } [ virtual ] class [ lifetime ] class_identifier [ parameter_port_list ]

[ extends class_identifier [ parameter_value_assignment ] ] ; [ timeunits_declaration ]

{ class_item }

endclass [ : class_identifier]

LRM-65 LRM-99

Change Syntax 11-1 (change in red):

class_item ::=

  { attribute_instance } class_property

| { attribute_instance } class_method

| { attribute_instance } class_constraint

            | { attribute_instance } type_declaration

                | { attribute_instance } class_declaration

| { attribute_instance } timeunits_declaration21

Section 11.3

LRM-48

Change (change in red):

A class is a type that includes data and subroutines (functions and tasks) that operate on that data. A class’s data is referred to as class properties, and its subroutines are called methods, both are members of the class. The class properties and methods, taken together, define the contents and capabilities of some kind of object.

Section 11.5

LRM-48

Change (change in red):

The data fields of an object can be used by qualifying class property names with an instance name. Using the earlier example, the commands for the Packet object p can be used as follows:

Section 11.6

LRM-48

Change (change in red):

An object’s methods can be accessed using the same syntax used to access class properties:

Section 11.7

LRM-49

Change (change in red):

Section 11.7

The new operation is defined as a function with no return type, and like any other function, it must be nonblocking. Even though new does not specify a return type, the left-hand side of the assignment determines the return type.

 

Class properties that include an initializer in their declaration are initialized before the execution of the user-defined class constructor. Thus, initializer values can be overriden by the class constructor

Section 11.8

LRM-48

Change (change in red):

11.8 Static class properties

 

The previous examples have only declared instance class properties. Each instance of the class (i.e., each object of type Packet), has its own copy of each of its six variables. Sometimes only one version of a variable is required to be shared by all instances. These class properties are created using the keyword static. Thus, for example, in a case where all instances of a class need access to a common file descriptor:

LRM-50

Change (change in red):

Now, fileID shall be created and initialized once. Thereafter, every Packet object can access the file descriptor in the usual way:

 

Packet p;

c = $fgetc( p.fileID );

 

Note that static class properties can be used without creating an object of that type.

Section 11.9

LRM-48

Change (change in red):

 

Methods can be declared as static. A static method is subject to all the class scoping and access rules, but behaves like a regular subroutine that can be called outside the class, even with no class instantiation. A static method has no access to non-static members (class properties or methods), but it can directly access static class properties or call static methods of the same class. Access to non-static members or to the special this handle within the body of a static method is illegal and results in a compiler error. Static methods cannot be virtual.

Section 11.10

LRM-48

Change (change in red):

 

The this keyword is used to unambiguously refer to class properties or methods of the current instance. The this keyword denotes a predefined object handle that refers to the object that was used to invoke the subroutine that this is used within. The this keyword shall only be used within non-static class methods, otherwise an error shall be issued. For example, the following declaration is a common way to write an initialization task:

LRM-48

Change (change in red):

 

The x is now both a property of the class and an argument to the function new. In the function new, an unqualified reference to x shall be resolved by looking at the innermost scope, in this case the subroutine argument declaration. To access the instance class property, it is qualified with the this keyword, to refer to the current instance.

Section 11.11

LRM-48

Change (change in red):

 

The last statement has new executing a second time, thus creating a new object p2, whose class properties are copied from p1. This is known as a shallow copy. All of the variables are copied across: integers, strings, instance handles, etc. Objects, however, are not copied, only their handles; as before, two names for the same object have been created. This is true even if the class declaration includes the instantiation operator new:

LRM-48

Change (change in red):

 

Several things are noteworthy. First, class properties and instantiated objects can be initialized directly in a class declaration. Second, the shallow copy does not copy objects. Third, instance qualifications can be chained as needed to reach into objects or to reach through objects:

Section 11.12

LRM-48

Change (change in red):

To refer to a class property of Packet, the variable packet_c needs to be referenced.

LRM-48

Change (change in red):

Now, all of the methods and class properties of Packet are part of LinkedPacket—as if they were defined in LinkedPacket—and LinkedPacket has additional class properties and methods.

Section 11.13

LRM-48

Change (change in red):

In this case, references to p access the methods and class properties of the Packet class. So, for example, if class properties and methods in LinkedPacket are overridden, these overridden members referred to through p get the original members in the Packet class. From p, new and all overridden members in LinkedPacket are now hidden.

Section 11.17

LRM-48

Change (change in red):

So far, all class properties and methods have been made available to the outside world without restriction. Often, it is desirable to restrict access to class properties and methods from outside the class by hiding their names. This keeps other programmers from relying on a specific implementation, and it also protects against accidental modifications to class properties that are internal to the class. When all data becomes hidden—being accessed only by public methods—testing and maintenance of the code becomes much easier.

 

In SystemVerilog, unqualified class properties and methods are public, available to anyone who has access to the object’s name.

 

A member identified as local is available only to methods inside the class. Further, these local members are not visible within subclasses. Of course, non-local methods that access local class properties or methods can be inherited, and work properly as methods of the subclass.

 

A protected class property or method has all of the characteristics of a local member, except that it can be inherited; it is visible to subclasses.

 

Note that within the class, a local method or class property of the class can be referenced, even if it is in a different instance. For example:

 

class Packet;

local integer i;

function integer compare (Packet other);

compare = (this.i == other.i);

endfunction

endclass

 

A strict interpretation of encapsulation might say that other.i should not be visible inside of this packet, since it is a local class property being referenced from outside its instance. Within the same class, however, these references are allowed. In this case, this.i shall be compared to other.i and the result of the logical comparison returned.

 

Class members can be identified as either local or protected; class properties can be further defined as const, and methods can be defined as virtual. There is no predefined ordering for specifying these modifiers; however, they can only appear once per member. It shall be an error to define members to be both local and protected, or to duplicate any of the other modifiers.

Section 11.18

LRM-48

Change (change in red):

11.18 Constant Class Properties

 

Class properties can be made read-only by a const declaration like any other SystemVerilog variable. However, because class objects are dynamic objects, class properties allow two forms of read-only variables: global constants and instance constants.

 

Global constant class properties are those that include an initial value as part of their declaration. They are similar to other const variables in that they cannot be assigned a value anywhere other than in the declaration.

Section 11.19

LRM-51

Change (change in red):

Abstract classes can also have virtual methods. Virtual methods are a basic polymorphic construct. A virtual method overrides a method in all the base classes, whereas a normal method only overrides a method in that class and its descendants. One way to view this is that there is only one implementation of a virtual method per class hierarchy, and it is always the one in the latest derived class. Virtual methods provide prototypes for subroutines, all of the information generally found on the first line of a method declaration: the encapsulation criteria, the type and number of arguments, and the return type if it is needed. Later, when subclasses override virtual methods, they must follow the prototype exactly. Thus, all versions of the virtual method look identical in all subclasses:

LRM-52

Change (change in red):

virtual class BasePacket;

virtual protected function integer send(bit[31:0] data);

endfunction

endclass

 

class EtherPacket extends BasePacket;

protected function integer send(bit[31:0] data);

// body of the function

...

endfunction

endclass

Section 11.21

LRM-48

Change (change in red):

Because classes and other scopes can have the same identifiers, the scope resolution operator uniquely identifies a member of a particular class. In addition, to disambiguating class scope identifiers, the :: operator also allows access to static members (class properties and methods) from outside the class, as well as access to public or protected elements of a super-classes from within the derived classes.

LRM-48

Change (change in red):

The scope resolution operator enables:

 

      Access to static public members (methods and class properties) from outside the class hierarchy.

Section 11.22

LRM-53

Change (change in red):

The out of block method declaration must match the prototype declaration exactly; the only syntactical difference is that the method name is preceded by the class name and scope operator (::).

 

Out of block declarations must be declared in the same scope as the class declaration.

Section 11.23

LRM-86

Change (change in red):

class vector #(parameter int size = 1;);

bit [size-1:0] a;

endclass

LRM-86

Change (change in red):

class stack #(parameter type T = int;);

local T items[];

task push( T a ); ... endtask

task pop( ref T a ); ... endtask

endclass

LRM-86

Change (change in red):

class vector #( parameter int size = 1;);

bit [size-1:0] a;

static int count = 0;

function void disp_count();

$display( "count: %d of size %d", count, size );

endfunction

endclass

LRM-57

Change (change in red):

To avoid having to repeat the specialization either in the declaration or to create parameters of that type, a typedef should be used:

 

typedef vector#(4) Vfour;

typedef stack#(Vfour) Stack4;

Stack4 s1, s2;             // declare objects of type Stack4

 

A parameterized class can extend another parameterized class. For example:


class C #(parameter type T = bit); ... endclass               // base class
class D1 #(parameter type P = real) extends C;                // T is bit (the default)
class D2 #(parameter type P = real) extends C #(integer);     // T is integer
class D3 #(parameter type P = real) extends C #(P);           // T is P

 

Class D1 extends the base class C using the base class's default type (bit) parameter. Class D2 extends the base class C using an integer parameter. Class D3 extends the base class C using the parameterized type (P) with which the extended class is parameterized.

Section 11.24

LRM-64

Change (change in red):

typedef class C2;          // C2 is declared to be of type class

class C1;

C2 c;

endclass

class C2;

C1 c;

endclass