SystemVerilog
Classes
Ahmed Hemani
System Architecture and Methodology Group
Department of Electronic and Computer Systems
School of ICT, KTH
Class
Class is a generalization of the data type concept;
Object is an instance of the class
Class is central to the Object Oriented Design:
Encapsulation of Data and Algorithm as an object
Inheritance, Polymorphism
A class is a type that includes data and subroutines (functions
and tasks) that operate on that data.
A classs 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.
class Packet ;
//data or class properties
bit [3:0] command;
bit [40:0] address;
bit [4:0] master_id;
integer time_requested;
integer time_issued;
integer status;
// initialization
function new();
command = IDLE;
address = 41b0;
master_id = 5bx;
endfunction
// methods. public access entry points
task clean();
command = 0; address = 0; master_id = 5bx;
endtask
task issue_request( int delay );
// send request to bus
endtask
function integer current_status();
current_status = status;
endfunction
endclass
Instantiating a Class
1.
2.
Declare the class variable.
Create the object by invoking the new method.
packet p; // declare a variable of class Packet
p = new; // initialize variable to a new allocated
// object of the class Packet
Un-initialized object handles are set by default to the special value null.
An un-initialized object can be detected by comparing its handle with null.
class obj_example;
...
endclass
task task1(integer a, obj_example myexample);
if (myexample == null) myexample = new;
endtask
Object Properties and Methods
The data fields of an object can be used by qualifying
class property names with an instance name.
Packet p = new;
p.command = INIT;
p.address = $random;
packet_time = p.time_requested;
Packet p = new;
status = p.current_status();
Note that the assignment to status is not:
status = current_status(p);
A class properties are freely and broadly available to the methods of
the class, but each method only accesses the properties associated with
its object, i.e., its instance.
Constructor
Every class has a default constructor method called new
New allocates memory for the object. Garbage collection available
The new operation is defined as a function with no return type, the
left-hand side of the assignment determines the return type.
It is also possible to pass arguments to the constructor, which
allows run-time customization of an object.
Packet p = new(STARTUP, $random, $time);
function new(int cmd = IDLE, bit[12:0] adrs = 0, int cmd_time );
command = cmd;
address = adrs;
time_requested = cmd_time;
endfunction
Static Class Properties
By default, all instances (objects) of a class have their own
copies of data objects (properties)
When all instances of a class want to have only one shared
copy of property, it is declared as static
class Packet ;
static integer fileId = $fopen( "data", "r" );
endclass
Packet p;
c = $fgetc( p.fileID );
Note that static class properties can be used without creating an
object of that type.
Static Methods
Methods can be declared as static.
A static method can be called outside the class, even with no class
instantiation.
A static method has no access to non-static members, but it can directly
access static class properties or call static methods of the same class.
class id;
static int current = 0;
static function int next_id();
next_id = ++current; // OK to access static property
endfunction
endclass
Static Method vs. Method with static lifetime
class TwoTasks;
static task foo(); ... endtask // static class method with
// automatic variable lifetime
task static bar(); ... endtask // non-static class method with
// static variable lifetime
endclass
THIS
The this keyword is used to unambiguously refer to (non-static)
class properties or methods of the current instance.
class Demo ;
integer x;
function new (integer x)
this.x = x;
endfunction
endclass
Copying Objects
Assignment: Simple Copy
The object is not copied, only the handle/pointer is copied
Packet p2;
p2 = p1;
Shallow Copy: Only the first level properties are copied.
Properties that are objects are not copied, just their handles/pointers
class A; integer j = 5;
endclass
class B; integer i = 1; A a = new; endclass
function integer test;
B b1 = new; // Create an object of class B
B b2 = new b1; // Create an object that is a copy of b1
b2.i = 10; // i is changed in b2, but not in b1
b2.a.j = 50; // change a.j, shared by both b1 and b2
test = b1.i; // test is set to 1 (b1.i has not changed)
test = b1.a.j; // test is set to 50 (a.j has changed)
endfunction
Deep copy requires custom methods
Inheritance and subclasses
Inheritance allows extending an existing class with more
properties and methods while inheriting the properties and
methods of the parent class
Inheritance enables and encourages reuse and easy to
maintain code
class LinkedPacket extends Packet;
LinkedPacket next;
function LinkedPacket get_next();
get_next = next;
endfunction
endclass
SystemVerilog restricts inheritance to single inheritance
The parents methods can be overridden by the methods in the
sub-class the child class
Super
The super keyword is used from within a derived class to refer
to members of the parent class.
It is necessary to use super to access members of a parent
class when those members are overridden by the derived class.
class Packet; //parent class
integer value;
function integer delay();
delay = value * value;
endfunction
endclass
class LinkedPacket extends Packet; //derived class
integer value;
function integer delay();
delay = super.delay()+ value * super.value;
endfunction
endclass
Data hiding and Encapsulation
By default, all properties and methods are visible in the
scope in which the object is visible.
This is not always desirable. To prevent accidental and
incorrect manipulation of class properties and invocation of
methods, they can be declared as local or protected.
This improves maintainability of the code.
Local members are available to methods inside the class.
Local members are not visible within subclasses and cannot
be inherited.
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.
class Packet;
local integer i;
function integer compare (Packet other);
compare = (this.i == other.i);
endfunction
endclass
Constants
Global constants have an initial value as part of their declaration
Global constants are also often declared static
class Jumbo_Packet;
const int max_size = 9 * 1024; // global constant
byte payload [];
function new( int size );
payload = new[ size > max_size ? max_size : size];
endfunction
endclass
Instance constants are assigned values in their constructors
Instance constants cannot be static
class Jumbo_Packet;
const int max_size; // Instance constant
byte payload [];
function new( int size );
max_size = $random % 4096;
payload = new[ size > max_size ? max_size : size];
endfunction
endclass
Virtual Class & Methods
Virtual class & methods are a way of creating a template.
From such a template, real classes are derived.
Virtual classes can have virtual methods that should be
overridden by the derived classes.
Virtual Class is the basic polymorphic construct.
virtual class BasePacket;
Set of virtual methods that
all derived classes have
Ethernet packets,
token ring packets,
GPSS packets,
satellite packets
These classes could differ
significantly but all have methods
that overrides the methods in the
parent virtual class
Polymorphism
virtual class BasePacket;
virtual function integer send(bit[31:0] data); endfunction
endclass
class EtherPacket extends BasePacket;
function integer send(bit[31:0] data);
// body of the function
...
endfunction
endclass
. . .
class TokenPacket . . .
BasePacket packets[100];
Now, instances of various packet objects can be created, and put into the array:
EtherPacket ep = new; // extends BasePacket
TokenPacket tp = new; // extends BasePacket
packets[0] = ep;
packets[1] = tp;
//compile time decision which send will be invoked
packets[1].send();
Class Scope Operator ::
:: is used to disambiguate identifiers in different scopes
Can be used with static elements of a class, static class
properties, static methods, typedefs, enumerations,
structures, unions, and nested class declarations
Class-scope resolved expressions can be read (in
expressions), written (in assignments or subroutines calls) or
triggered off (in event expressions).
They can also be used as the name of a type or a method call
class Base;
typedef enum {bin,oct,dec,hex} radix;
static task print( radix r, int n ); ... endtask
endclass
...
Base b = new;
int bin = 123;
b.print( Base::bin, bin ); // Base::bin and bin are different
Base::print( Base::hex, 66 );
class StringList;
class Node; // Nested class for a node in a linked list.
string name;
Node link;
endclass
endclass
class StringTree;
class Node; // Nested class for a node in a binary tree.
string name;
Node left, right;
endclass
endclass
// StringList::Node is different from StringTree::Node
Out of Block Declaration
Method definitions can be moved out of the Class definition body.
This makes the Class definition less cluttered.
Methods that are defined externally are declared within the class
with extern qualifier, function name and parameters.
Externally, the class name and scope operator qualifies and binds
the method declaration with the class.
class Packet;
Packet next;
function Packet get_next(); get_next = next; endfunction
// out-of-body (extern) declaration
extern protected virtual function int send(int value);
endclass
function int Packet::send(int value);
// dropped protected virtual, added Packet::
// body of method
...
endfunction
10
Parameterized Classes
Classes can be made generic to size and data type
class vector #(int size = 1);
bit [size-1:0] a;
endclass
vector #(10) vten; // object with vector of size 10
vector #(.size(2)) vtwo; // object with vector of size 2
typedef vector#(4) Vfour; // Class with vector of size 4
class stack #(type T = int);
local T items[];
task push( T a ); ... endtask
task pop( ref T a ); ... endtask
endclass
stack#(bit[1:10]) bs; // a stack of 10-bit vector
stack#(real) rs; // a stack of real numbers
11