CummingsSNUG2009Boston SVVirtual
CummingsSNUG2009Boston SVVirtual
Boston, MA
Voted Best Paper
2nd Place
www.sunburst-design.com hmcdv.iwarp.com
ABSTRACT
The SystemVerilog keyword virtual is used in three very distinct ways within the language.
This paper introduces the fundamentals that are required to understand how virtual is used and
behaves with virtual classes, virtual methods and virtual interface instances, and how it adds
polymorphism within a SystemVerilog context. This paper also introduces pure virtual
methods and pure constraints, features added to the IEEE-1800-2009 SystemVerilog Standard
and how pure virtual methods are already in use today.
Table of Examples
Example 1 - Simple class declaration: base1 .................................................................................. 6
Example 2 - Class declaration with handle declaration: base1 b1; ................................................. 6
Example 3 - Construction of the b1 object handle using the new() constructor ............................. 7
Example 4 - Construction of the b1 object handle using the new() constructor at time 10 ............ 7
Example 5 - Reconstruction of the b1 object handle removes the first b1 object ........................... 8
Example 6 - BAD: null b1 object handle causes fatal run-time null-object-handle access for
show() method ................................................................................................................................ 9
Example 7 - Cmd base class base and extended NewCmd class .................................................. 10
Example 8 - Example of extended pre-method functionality ....................................................... 11
Example 9 - Example of extended post-method functionality ...................................................... 12
Example 10 - Use of "this" command to access class data member rather than method argument
....................................................................................................................................................... 14
Example 11 - Valid virtual class declaration with subsequent virtual class handle declaration ... 15
Example 12 - BAD - attempt to construct "new();" a virtual class handle ................................... 15
Example 13 - Valid virtual method - matching argument and return types .................................. 17
Example 14 - BAD virtual method - argument name does not match .......................................... 18
Example 15 - BAD virtual method - argument type does not match ............................................ 19
Example 16 - BAD virtual method - argument direction does not match .................................... 20
Example 17 - BAD virtual method - number of arguments does not match................................. 21
Example 18 - BAD virtual method - return type does not match ................................................. 22
Example 19 - Valid virtual class with pure virtual method and declared class handle ................. 24
Example 20 - BAD pure virtual method with "endfunction" declaration ..................................... 24
Example 21 - BAD use of pure - pure can only be used with virtual methods ............................. 24
Example 22 - Valid pure virtual methods must be extended in a non-virtual class ...................... 25
Example 23 - BAD - pure virtual methods must be extended with the same argument and return
types .............................................................................................................................................. 26
Example 24 - BAD - pure virtual methods MUST be extended in the first non-virtual class ...... 27
This paper will detail how the virtual keyword is used to create abstract classes, runtime and
polymorphic class methods and interfaces between a static design and a dynamic verification en-
vironment.
This paper will also introduce the SystemVerilog 2009 keyword pure, how pure methods and
constraints work, how pure methods have already been added to some SystemVerilog simulator
implementations and the simple work-around to make pure methods work in all SystemVerilog-
2005 implementations.
It is always easier to use a language feature if one knows how the feature works and the prob-
lems the feature solves. It is the intent of this paper to provide this background education on the
powerful virtual and pure features of SystemVerilog-2005 and 2009.
If you are already familiar with SystemVerilog class basics, you can skip to section 3.
2.1 What is a class?
A class is a dynamic type definition that includes data members (commonly referred to as prop-
erties or field members in Object Oriented Programming) and SystemVerilog tasks and functions
that are intended to interact with the data members. Tasks and functions defined within a class
are often referred to as methods, both in Object Oriented Programming and in SystemVerilog.
class base1;
bit [7:0] a;
program example2;
class base1;
bit [7:0] a;
Handles can be constructed or they can be assigned the values of extended class handles of the
same base class type. More on this later.
2.3 Handles -vs- pointers
In C and C++, a pointer can be mathematically manipulated. If the wrong value is added to a
pointer, the pointer might not point to valid data and the program behaviour referencing the inva-
lid pointer can execute with completely unexpected behaviour.
Like Java, SystemVerilog handles cannot be mathematically manipulated; therefore, they do not
allow the execution of unexpected program code, which is possible in C and C++.
program example3;
class base1;
bit [7:0] a;
In Example 3, the b1 handle of base1 type is constructed using the new() constructor. Once
an object is constructed, the handle can be used to call class methods. The set_show method is
called in the initial block using the b1 handle.
Classes are dynamic types and class objects can be constructed during run time. In Example 3,
the object was constructed during declaration of the b1 class handle at time 0. In Example 4, the
b1 class handle was declared as a stand-alone statement, then the b1 handle was constructed in
the initial block at time 10.
program example4;
class base1;
bit [7:0] a;
base1 b1;
initial begin
b1 object constructed
#10 b1 = new();
at time-10
b1.set_show(8'h55);
end
endprogram
Example 4 - Construction of the b1 object handle using the new() constructor at time 10
Constructing an object with the name of an existing object handle destroys the previous object.
In Example 5, the b1 handle is reconstructed at time 10, causing any reference to the original b1
handle to be lost. The first call to the b1.show() method returns the value of 55. The second
call to the b1.show() method returns the default, uninitialized value for the a variable, which
is 00.
program example5;
class base1;
bit [7:0] a;
program example6;
class base1;
bit [7:0] a;
base1 b1 = new();
initial begin
b1.set(8'h55); Set b1 handle to null
b1.show();
#10
b1 = null; Run-time fatal reference
b1.show();
to null object
end
endprogram
Example 6 - BAD: null b1 object handle causes fatal run-time null-object-handle access for show() method
Garbage collection is automatic in SystemVerilog. When there are no longer any handles that
point to the object, there is no longer a way to access the object data and method so the object
storage space is removed and recovered from use. This is called garbage collection, or in other
words, recycling the unused memory. If the unused memory space were not recycled, it would be
possible to eventually use up all of the available simulation memory by leaving chunks of
memory lying around until we run out of memory. This condition is referred to as memory leaks;
we keep leaking chunks of memory by not recycling the storage during simulation.
3 Class extension
To create a second copy of a base class with modifications, we use the keyword extends to
copy all of the base class data members and methods into the extended class and then add-to or
modify the base class data and methods.
Example 7 shows two command classes that will be used in another example later in the paper.
The Cmd class is the base class with four data members, a, b, opcode, cycle, and one virtual
void function (class method). In the Cmd class, the printmsg method displays the two random-
ized data members a and b, concatenated together and displayed as a single hex value. The
class Cmd;
rand bit [15:0] a, b;
rand op_e opcode;
rand bit cycle;
To make a second copy of this class type with all of the same data members but with a modified
(overridden) printmsg method, the Cmd class is extended using the extends keyword to
form a NewCmd class that displays the printmsg-method data as two separate hex values for a
and b respectively, along with the a display of the opcode name as opposed to its hex value.
3.1 Override versus overload
In SystemVerilog, an extended class can override a base class method by the same name, but
there is no such thing as overloaded methods.
The distinction between override and overload is this: override replaces the base class method
completely in the extended class. Overloading a method would allow more than one version of a
method by the same name to exist and the method called would be based on the data types of the
arguments passed to the method. Due to the implementation difficulty of working with loose data
types in Verilog and SystemVerilog, method and function overloading in SystemVerilog is not
supported.
When extending a method in an extended class, it is legal to add functionality before the corre-
sponding method functionality in the base class. Example 8 shows an extended method that uses
a super.<method> call in an extended class.
program example8;
class Base1;
bit [7:0] d1, d2, csum;
virtual function void set (bit [7:0] val1='0, bit [7:0] val2=8’hAA);
d1 = val1;
d2 = val2;
endfunction
Base1 b1 = new();
Ext1 e1 = new();
initial begin
b1.set(8'h01);
b1.calc_csum(8'h03);
b1.show();
e1.set(8'h01);
e1.calc_csum(8'h03);
e1.show();
end
endprogram
Example 8 - Example of extended pre-method functionality
program example9;
class Base1;
bit [7:0] d1, d2, csum;
virtual function void set (bit [7:0] val1='0, bit [7:0] val2=8'hAA);
d1 = val1;
d2 = val2;
endfunction
Base1 b1 = new();
Ext1 e1 = new();
initial begin
b1.set(8'h01);
b1.calc_csum(8'h03);
b1.show();
e1.set(8'h01);
e1.calc_csum(8'h03);
e1.show();
end
endprogram
Example 9 - Example of extended post-method functionality
There are a few more details about the super keyword that need to be understood.
The super keyword cannot be used in a top-level base class since there is no parent class that
could be referenced with the super keyword.
In a UNIX file system, one often references a file or executable from a parent directory using the
"../" notation. For example, to change directories to the parent directory, one would execute
the command: cd ..
The super command is analogous to the ../ notation used in a UNIX file system, but unlike
the UNIX file system, SystemVerilog does not permit reference to a data member or method up
two or more levels of base classes. The following syntax would be illegal:
super.super.gen_crc
You are only allowed to immediately reference one-level of super. If you need to reference a
method that is two levels up from the current class definition, you will have to reference the
super.<method> and that method will have to reference its super.<method>.
The this command is analogous to the ./ notation used in a UNIX file system to access cur-
rent directory information. For example, to run the script foo that is in the local directory, one
would execute the command: ./foo
In Example 10, this.i1 is used to access the data member of the current class definition rather
than the argument i1 of the set method (it is recommended to avoid coding styles that need to
use the this command). Without using the this command, the method would only be able to
access the argument i1 passed in to it. The bad_set method takes the passed in argument
value and writes it back to the argument so that when the show method is called after bad_set,
it shows the same value for i1 that was set using the previous set method call.
program example10;
class base1;
bit [7:0] i1;
A virtual class is often referred to as an abstract class that cannot be directly constructed.
The virtual class is intended to create a template for classes that are extensions of the virtual
class. The virtual class is not intended to be constructed and used directly, but different forms of
the extended class are frequently generated in a constrained random testbench and then assigned
to a virtual class handle for consistent execution of the pre-defined legal class methods.
In Example 11, a virtual base1 class is declared, and subsequently a virtual class handle
called b1 is declared to be of the base1 type. It is permitted to declare a virtual class handle
and this is frequently done in advanced verification methodologies.
program example11;
virtual class base1;
virtual function void showit (arg1_t i1);
$display("base1 : arg1_t = %2h", i1);
endfunction
endclass **VALID**
virtual class handle
base1 b1;
declaration
endprogram
Example 11 - Valid virtual class declaration with subsequent virtual class handle declaration
In Example 12, the same virtual base1 class is declared but then an attempt is made to
declare and construct a b1 handle of the virtual base1 class type. This is illegal.
program example12;
virtual class base1;
virtual function void showit (arg1_t i1);
$display("base1 : arg1_t = %2h", i1);
endfunction
endclass
**ERROR**
base1 b1 = new(); attempt to construct
endprogram virtual class object
Example 12 - BAD - attempt to construct "new();" a virtual class handle
There is a common misconception that all methods declared in a virtual class are automatically
virtual methods. This is not true. For method to be virtual, it must be declared virtual, even in
virtual classes.
5 Class methods
Class methods can be divided into three categories:
Regular class methods (non-virtual methods).
Virtual class methods.
Pure virtual class methods.
6 Non-virtual methods
Any class function or task that does not include the virtual keyword is a non-virtual method.
Non-virtual methods can be defined in both classes and virtual classes.
Non-virtual methods do not generally lend themselves well to polymorphism and advanced veri-
fication methodologies, so the examples of non-virtual methods and accompanying legal exam-
ples of same are de-emphasized in this paper and therefore have been demoted to the appendix
(see section 16 for Appendix examples).
7 virtual methods
Virtual methods require all arguments and types to be the same in the corresponding extended
methods.
Virtual methods impose one very important restriction in extended classes: virtual methods force
the use of the exact same number of arguments and the exact same argument and return types
when the method is extended. Non-virtual methods do not.
Virtual methods differ from non-virtual methods in that the number, types and names of the ar-
guments, as well as the return type, must match the same arguments and types as the base class
method, if overridden. An extended non-virtual method is allowed to change every calling and
return detail of the base class method by the same name.
The ext1 class is a valid extension of the base1 class because it too has (a) a 1-bit return type,
(b) just one argument that is also an input argument, and (c) the input argument is also the
arg1_t type.
program example13;
class base1; Extended class with
virtual function bit showit (arg1_t i1); virtual "showit" method
$display ("\n\n %m: i1=%0d \n\n", i1);
endfunction
**VALID**
endclass
all argument and return
types match
class ext1 extends base1;
virtual function bit showit (arg1_t i1);
$display ("\n\n EXT: %m: i1=%0d \n\n", i1);
return(1);
endfunction
endclass
base1 b1 = new();
ext1 e1 = new();
bit status;
initial begin
status=b1.showit(25);
status=e1.showit(33);
end
endprogram
Example 13 - Valid virtual method - matching argument and return types
program example14;
class base1;
virtual function bit showit (arg1_t i1);
$display ("\n\n %m: i1=%0d \n\n", i1);
endfunction
**ERROR**
endclass
argument name does not
match
class ext1 extends base1;
virtual function bit showit (arg2_t in1);
$display ("\n\n EXT: %m: i1=%0d \n\n", i1);
return(0);
endfunction
endclass
base1 b1 = new();
ext1 e1 = new();
bit status;
initial begin
status=b1.showit(25);
status=e1.showit(33);
end
endprogram
Example 14 - BAD virtual method - argument name does not match
program example15;
class base1;
virtual function bit showit (arg1_t i1);
$display ("\n\n %m: i1=%0d \n\n", i1);
endfunction
**ERROR**
endclass
argument type does not
match
class ext1 extends base1;
virtual function bit showit (arg2_t i1);
$display ("\n\n EXT: %m: i1=%0d \n\n", i1);
return(0);
endfunction
endclass
base1 b1 = new();
ext1 e1 = new();
bit status;
initial begin
status=b1.showit(25);
status=e1.showit(33);
end
endprogram
Example 15 - BAD virtual method - argument type does not match
program example16;
class base1;
virtual function bit showit (arg1_t i1);
$display ("\n\n %m: i1=%0d \n\n", i1);
endfunction **ERROR**
endclass argument direction does
not match
class ext1 extends base1;
virtual function bit showit (output arg1_t i1);
$display ("\n\n EXT: %m: i1=%0d \n\n", i1);
return(0);
endfunction
endclass
base1 b1 = new();
ext1 e1 = new();
bit status;
initial begin
status=b1.showit(25);
status=e1.showit(33);
end
endprogram
Example 16 - BAD virtual method - argument direction does not match
program example17;
class base1;
virtual function bit showit (arg1_t i1);
$display ("\n\n %m: i1=%0d \n\n", i1);
endfunction **ERROR**
endclass number of arguments
does not match
class ext1 extends base1;
virtual function bit showit (arg1_t i1, i2=55);
$display ("\n\n EXT: %m: i1=%0d i2=%0d \n\n", i1, i2);
return(0);
endfunction
endclass
base1 b1 = new();
ext1 e1 = new();
bit status;
initial begin
status=b1.showit(25);
status=e1.showit(33);
end
endprogram
Example 17 - BAD virtual method - number of arguments does not match
program example18;
class base1;
virtual function bit showit (arg1_t i1);
$display ("\n\n %m: i1=%0d \n\n", i1);
endfunction **ERROR**
endclass funciton return type does
not match
class ext1 extends base1;
virtual function logic showit (arg1_t i1);
$display ("\n\n EXT: %m: i1=%0d \n\n", i1);
return(0);
endfunction
endclass
base1 b1 = new();
ext1 e1 = new();
bit status;
initial begin
status=b1.showit(25);
status=e1.showit(33);
end
endprogram
Example 18 - BAD virtual method - return type does not match
Virtual methods are an important part of polymorphism (see section 11). By requiring all virtual
methods to exactly match the number, names and types of arguments used in the base class
method, it is possible to make a base class handle point to an extended class object derived from
the common base class and call the base class methods with full confidence that calling the
method in either the base class or extended class will be valid, even if the base and extended
class methods execute different code inside of the methods.
7.1 Once virtual, always virtual
If the base class declares a method to be virtual, the extended class method by the same name
is also virtual, even if it is not declared to be virtual. The virtual keyword is essentially a
"sticky" keyword that sticks to all extended classes with methods by that same name. There is no
way to remove the virtual stickiness from an extended method by the same name.
Guideline: To avoid confusion, declare all virtual methods in extended classes with the
virtual keyword.
The best way to think of the pure keyword is that it imposes three immediate restrictions on a
class based methodology, and these restriction are checked by the compiler:
(1) The definition of pure methods and constraints is only allowed in an abstract class
(virtual class).
(2) A virtual method or constraint shall not have an implementation in the virtual class (the
method or constraint must be empty).
(3) The virtual class or method MUST be overridden in the first non-virtual extended class based
on the abstract class.
The pure virtual method is either a pure virtual task or pure virtual
function prototype that is not allowed to have an implementation (no body code allowed) and
is not even allowed to have an endtask or endfunction keyword to close the pure virtual
method.
In Example 20 shows a common new user mistake. Even though the pure virtual
function has no function-body code, the function erroneously includes an endfunction
keyword. This program will not compile.
program example20;
virtual class base1;
pure virtual function bit showit (arg1_t i1); **ERROR**
endfunction "endfunction" not permitted
endclass on a pure virtual method
base1 b1;
endprogram
Example 20 - BAD pure virtual method with "endfunction" declaration
In Example 21, a virtual class is defined but the pure keyword was erroneously added to
a non-virtual method. This program will not compile.
program example21;
virtual class base1;
pure function bit showit (arg1_t i1);
endclass **ERROR**
"pure" NOT VALID with
base1 b1; non-virtual functions
endprogram
Example 21 - BAD use of pure - pure can only be used with virtual methods
In Example 22, a virtual base1 class includes a properly coded showit pure virtual method.
The ext1 non-virtual class extends the base1 base class and is required to also extend the
showit pure virtual method with actual method functionality as shown.
program example22;
virtual class base1;
pure virtual function bit showit (arg1_t i1);
endclass
base1 b1;
**VALID**
Non-virtual class extends virtual
class and properly extends the
class ext1 extends base1; pure virtual method
virtual function bit showit (arg1_t i1);
$display ("\n\n EXT: %m: i1=%0d \n\n", i1);
return(1);
endfunction
endclass
ext1 e1 = new();
bit status;
initial begin
status=e1.showit(33);
end
endprogram
Example 22 - Valid pure virtual methods must be extended in a non-virtual class
program example23;
virtual class base1;
pure virtual function bit showit (arg1_t i1);
endclass
**ERROR**
base1 b1; The pure virtual method is extended with
the wrong return type, wonrg number of
arguments and wrong argument directions
ext1 e1 = new();
bit status;
initial begin
status=e1.showit(33);
end
endprogram
Example 23 - BAD - pure virtual methods must be extended with the same argument and return types
program example24;
virtual class base1;
pure virtual function bit showit (arg1_t i1);
endclass
ext1 e1 = new();
bit status;
initial begin
status=e1.showit(33);
end
endprogram
Example 24 - BAD - pure virtual methods MUST be extended in the first non-virtual class
program example25;
virtual class base1;
pure virtual function bit showit (arg1_t i1);
endclass
base1 b1;
initial begin
status=e1.showit(33);
end
endprogram
Example 25 - BAD - pure virtual methods cannot be defined in a non-virtual class
program example26;
virtual class base1;
pure virtual function bit showit (arg1_t i1);
endclass
**VALID**
The pure virtual "showit" method is not
extended in the extended virtual class
virtual class ext1 extends base1;
// No override of pure virtual function showit
endclass
**VALID**
The pure virtual "showit" method is finally
extended in the extended non-virtual class
class ext2 extends ext1;
virtual function bit showit (arg1_t i1);
$display ("\n\n EXT2: %m: i1=%0d \n\n", i1);
return(1);
endfunction
endclass
ext2 e2 = new();
bit status;
initial begin
status=e2.showit(33);
end
endprogram
Example 26 - Valid - an extended virtual class does not have to extend a pure virtual method
program example27;
virtual class base1;
pure virtual function bit showit (arg1_t i1);
endclass
**VALID**
The pure virtual "showit" method is not
extended in the extended virtual class
virtual class ext1 extends base1;
// extended virtual class inherits pure virtual method
// from base class unless overriden
endclass
**ERROR**
First non-virtual class must override all
base class pure virtual methods
class ext2 extends ext1;
// No override of virtual function showit;
endclass
ext2 e2 = new();
bit status;
initial begin
status=e2.showit(33);
end
endprogram
Example 27 - BAD - First non-virtual class must override all inherited base class pure virtual methods
program example28;
virtual class base1;
pure virtual function bit showit (arg1_t i1);
endclass
**VALID**
The extended virtual class overrides the pure virtual
"showit" method from the base virtual class.
virtual class ext1 extends base1;
pure virtual function bit showit (arg1_t i1);
endclass
**ERROR**
First non-virtual class must override all
base class pure virtual methods
class ext2 extends ext1;
// No override of virtual function showit;
endclass
ext2 e2 = new();
bit status;
initial begin
status=e2.showit(33);
end
endprogram
Example 28 - BAD - First non-virtual class must override all declared base class pure virtual methods
program example29;
virtual class base1;
pure virtual function bit showit (arg1_t i1);
endclass
**VALID**
The pure virtual "showit" method IS
extended as a virtual method (not pure) in
virtual class ext1 extends base1; the extended virtual class
virtual function bit showit (arg1_t i1);
$display ("\n\n EXT1: %m: i1=%0d \n\n", i1);
return(1);
endfunction
endclass
**VALID**
The non-virtual class is NOT required to
override the virtual method (not pure) from
class ext2 extends ext1; the virtual class
// No override of virtual function showit;
endclass
ext2 e2 = new();
bit status;
initial begin
status=e2.showit(33);
end
endprogram
Example 29 - Valid - non-virtual class does not have to override non-pure methods from virtual base class
The simple work-around to replace a pure virtual function, as shown in Example 30, is
to build an empty function or task, to place them in a virtual class, and to require any engi-
neer who extends the virtual class with a non-virtual class to also extend the empty function or
task with some content (rules imposed by methodology as opposed to syntax).
The VMM class library uses another trick to mimic a pure virtual method. In the virtual
class vmm_notification from the vmm.sv file, shown in Example 31, the virtual
task reset() writes out and error message and terminates the simulation if it is called during
simulation.
Like pure virtual methods, a pure constraint must be defined in a virtual class
and must be overridden in the any non-virtual derived class. In the Example 32, the virtual
class D defines a data member that can be randomized, along with a pure constraint
called Test. The same example contains a non-virtual class E that is an extension of class D.
In the non-virtual class E, the constraint override is required.
virtual class D;
rand bit [7:0] data;
pure constraint Test;
endclass
class E extends D;
constraint Test {data>8'hC0;}
endclass
Example 32 - Pure constraint with override in non-virtual class
Pure constraints obligate all non-virtual extensions of the virtual class with pure constraints to
be overridden.
11 Polymorphism
Polymorphism is the concept of allowing an object or method to take on a different meaning
based on the context in which it is used.
Usually a virtual class is used as the common base type and a handle of the base virtual class is
declared to be used as the common interface to all of the extended classes.
An example of this, would be to create a virtual class of a network port that has various common
pure virtual methods for manipulating data (e.g. tx_data, rx_data, process_data). Then multiple
extensions (subtypes) of the network port class would be created, one for each required network
type (e.g. ethernet, atm, isdn). A handle of the base virtual class would be declared in the
testbench and the generic method names would be used to send, receive, and process data from
the device under test.
Based on which network port type the current device under test is using, an object of the appro-
priate extended class would be created and the base class handle would be pointed to it. When
the generic testbench calls one of the common methods through the base class handle, it is actu-
ally calling the extended class method, which can manipulate base class data fields and extended
class data fields.
program example33();
// Virtual base class declaration.
virtual class base1;
bit [7:0] id;
function new(int sid);
id = sid;
endfunction
pure virtual function void print_id();
endclass
base1 base;
ext1 e1 = new(0, 3); Polymorphically use a handle
ext2 e2 = new(1); of base class to access data
and methods of extended
initial begin class objects
base = e1;
base.print_id();
base = e2; // Output:
base.print_id(); // ID 0: E1 3
end // ID 1: E2
endprogram
Example 33 - Polymorphism example showing base class handle accessing extended classes
12 virtual interfaces
To understand how virtual interfaces work, a very brief explanation of interfaces is warranted.
12.1 Interfaces
An interface is a bundle of signals, much like a struct, with a few important differences.
A struct can be passed across a port, but all of the struct members must move in the same
direction. The entire struct is declared as an input, output, or inout. On the other hand, it
is possible to declare the interface members to move in different directions by means of the
modport (not explained in this paper).
An interface can also contain tasks, functions, assertions, and although not very
common, they can also contain other continuous assignments, initial procedures and
always procedures.
Declaring an interface is a lot like declaring a class. The interface is declared with signals (the
data members) and they can be declared with methods (tasks and functions). One notable differ-
ence between an interface and a class is that interfaces can have ports. Another notable differ-
ence is that when instantiated, an interface is static; that is, an interface is compiled and then
elaborated statically and permanently before the simulation runs. Classes are constructed dynam-
ically after elaboration and can be constructed and deleted throughout the simulation.
After being declared, an interface is instantiated and the instance name is really a handle to the
interface that allows the user to access the interface signals hierarchically using the interface in-
stance/handle name.
Modules that will be "connected" to the interface must declare a static interface handle of the
same type in the module header as an "interface port."
This allows the connecting module to reference the "connected" instantiated interface signals hi-
erarchically.
At the top-level where the interface is instantiated, we often say that the interface is then "con-
nected" to other modules, when in reality, we are simply assigning (passing) the interface in-
stance/handle to the static handles of the "connecting" modules. Once we pass the actual inter-
face instance/handle-name to the connecting modules, the connecting modules will now have a
local static handle-name that can be used to reference the actual, instantiated interface signals.
If you understand the concept of passing actual interface handles to make "connections," then it
is easier to grasp how virtual interfaces work, as described in the next section.
Declaring an interface to be virtual is a common method used to connect a dynamic object ori-
ented verification environment to a static design under test.
When first learning higher level SystemVerilog verification methodologies, this is not an easy
concept to grasp.
Consider the simple example of an alu_reg design as shown in Figure 1 with corresponding
SystemVerilog source code shown in Example 34.
always_comb begin
case (opcode)
PASSA: alu = data;
NAND : alu = ~(data & b);
OR : alu = data | b;
ADD : alu = data + b;
endcase
end
In order for a testbench to communicate with this design, a physical interface must be connected
to it and the design and interface should be enclosed within a top-level module as shown in
Figure 2. This is Step #1 as listed in Section 12.3.
Figure 2 - Top-level module with design (DUT), interface and clock generator
interface alu_if (
input logic [15:0] acc_out,
output logic [15:0] data,
output op_e opcode,
output logic load_a,
output logic load_b,
output logic rst_n,
input logic clk);
endinterface
The SystemVerilog interface code is shown in Example 35. All signals on the interface ports be-
come part of the interface bundle of signals. All interface I/O signals are declared as logic varia-
bles in the interface, except for any bi-directional signals, which are declared as wires (follows
good SystemVerilog data type usage guidelines).
module top;
`define CYCLE 10 logic [15:0] acc_out, data;
`timescale 1ns/1ns op_e opcode;
module clkgen (output logic clk); logic load_a, load_b,
initial begin logic rst_n, clk;
clk <= '0;
forever #(`CYCLE/2) clk = ~clk; clkgen clkgen (.*);
end alu_if aif (.*);
endmodule alu_reg alu_reg (.*);
endmodule
Example 36 - clkgen.sv SystemVerilog source code Example 37 - top.sv SystemVerilog source code
After declaring the interface code, a simple clkgen module can be coded as shown in Example
36, and the clkgen, alu_if and alu_reg modules are all instantiated into a top-level mod-
ule as shown in Example 37. The top-level module has an instance of the DUT, an instance of
the interface (this is the real interface, not a virtual interface), and the clock generator.
The Testbench class in Example 38 includes the code statement virtual alu_if vif;
which declares a handle ( vif ) to a virtual interface. This vif handle is used to make assign-
class Testbench;
Cmd c;
task stim;
assert(c.randomize);
c.printmsg();
if (c.opcode==PASSA) drive1;
else drive2;
@(negedge vif.clk);
endtask
The new() constructor includes an input argument of the alu_if interface handle type, with
handle name nif (new() interface). The input interface handle will be assigned to the virtual
interface handle vif, so the new() constructor input handle nif will be assigned to the virtual
interface handle vif, which means that the virtual interface will point to whatever the construc-
tor handle was pointing to as shown in Example 39.
Example 39 - Real interface handle aif assigned to new() handle nif, assigned to virtual interface handle vif
When the constructor is called to build a transactor object, the real interface handle ( aif ) will
be the handle that is passed to the constructor ( nif ), which will then be assigned to the virtual
interface handle ( vif ), which means that the virtual interface handle now points to the same
interface signals as the real interface handle.
Now when the transactor class writes to and reads from the virtual interface handle, it is actually
writing to and reading from the real interface handle, which is communicating directly with the
DUT. This is step #3 - the class-based testbench is now communicating directly with the DUT.
This is the magic! This is how we get a virtual interface to point to the real interface, and now all
class-based testing can be done over the virtual interface.
`timescale 1ns/1ns
`ifndef PKG1
`include "pkg1.sv"
`endif
class Cmd;
rand bit [15:0] a, b;
rand op_e opcode;
rand bit cycle;
program tb5;
Testbench tb;
Cmd b1=new();
NewCmd e1=new();
initial begin
tb = new(top4.aif, b1);
repeat(5) tb.stim();
tb = new(top4.aif, e1);
repeat(5) tb.stim();
tb.FINISH(2);
end
endprogram
The pure keyword allows methods and constraints to be added to an abstract class and to im-
pose the restriction that the functionality must be implemented to override the pure virtual
methods and pure constraints in extended classes.
If an engineer always overrode the empty virtual methods and empty constraints defined in a
base class, the pure keyword would never technically be needed, but the pure keyword allows
the compiler the catch such omissions in a class based environment.
Although not technically part of the SystemVerilog language until 2009, there are and have been
SystemVerilog simulators that have had the pure virtual methods implemented for a couple
of years and the pure virtual methods are already part of the OVM verification methodol-
ogy.
14 References
[1] "IEEE Standard For SystemVerilog - Unified Hardware Design, Specification and Verification Lan-
guage," IEEE Computer Society, IEEE, New York, NY, IEEE Std 1800-2005
[2] "IEEE P1800/D9 Standard For SystemVerilog - Unified Hardware Design, Specification and Verifi-
cation Language," To be published by the IEEE Computer Society, IEEE, New York, NY, IEEE
[3] EDA.org Mantis Database for SystemVerilog P8100:
www.eda-stds.org/svdb (login: guest / password: guest)
[4] Janick Bergeron, Eduard Cerny, Alan Hunter and Andrew Nightingale, "Verification Methodology
Manual for SystemVerilog," (VMM), Springer, www.springeronline.com, 2005.
[5] www.ovmworld.org - Version ovm-2.0.2 (June 2009)
[6] www.vmmcentral.org - Version vmm-1.1.1 (August 2009)
Cliff Cummings, President of Sunburst Design, Inc., is an independent EDA consultant and
trainer with 27 years of ASIC, FPGA and system design experience and 17 years of SystemVeri-
log, synthesis and methodology training experience.
Mr. Cummings has presented more than 100 SystemVerilog seminars and training classes in the
past six years and was the featured speaker at the world-wide SystemVerilog NOW! seminars.
Mr. Cummings holds a BSEE from Brigham Young University and an MSEE from Oregon State
University.
Sunburst Design, Inc. offers World Class Verilog & SystemVerilog training courses. For more
information, visit the www.sunburst-design.com web site.
Email address: cliffc@sunburst-design.com
Heath Chambers, President of HMC Design Verification, Inc., is an independent EDA consult-
ant and trainer with 13 years of ASIC and verification experience and 9 years of SystemVerilog,
Verilog and methodology training experience and 5 years of synthesis training experience.
Mr. Chambers has participated on IEEE & Accellera SystemVerilog committees, and is still an
active member of the IEEE SystemVerilog committees.
HMC Design Verification, Inc. offers verification consulting, and offers Verilog & SystemVeri-
log training through Sunburst Design. For more information, visit the hmcdv.iwarp.com web
site.
Email address: hmcdvi@msn.com
An updated version of this paper can be downloaded from the web sites:
www.sunburst-design.com/papers
hmcdv.iwarp.com/Papers
When extending non-virtual methods, almost anything is legal! The extended class simply over-
rides the base class method by name and there are no restrictions on the number, types and
names of the arguments, as well as the return type.
When an extended class handle is assigned to a base class handle the base class methods are still
referenced, which calls into question the value of making these extended-class to base-class han-
dle assignments.
It is obviously legal to override a base class method with an extended class method that has the
same number, types and names of the arguments, as well as the same return type, as shown in
Example 40.
program example40;
class base1;
function bit showit (arg1_t i1);
$display ("\n\n %m: i1=%0d \n\n", i1);
endfunction
endclass
**VALID**
all argument and return
types match
class ext1 extends base1;
function bit showit (arg1_t i1);
$display ("\n\n EXT: %m: i1=%0d \n\n", i1);
return(1);
endfunction
endclass
base1 b1 = new();
ext1 e1 = new();
bit status;
arg1_t dummy;
initial begin
status=b1.showit(25);
status=e1.showit(33);
end
endprogram
Example 40 - Non-virtual method overrides another method with matching argument and return types
program example41;
class base1;
function bit showit (arg1_t i1);
$display ("\n\n %m: i1=%0d \n\n", i1);
endfunction
endclass
**VALID**
argument types DO NOT
class ext1 extends base1; match
function bit showit (arg2_t i1);
$display ("\n\n EXT: %m: i1=%0d \n\n", i1);
return(0);
endfunction
endclass
base1 b1 = new();
ext1 e1 = new();
bit status;
arg1_t dummy;
initial begin
status=b1.showit(25);
status=e1.showit(33);
end
endprogram
Example 41 - Valid - Non-virtual method overrides another method with non-matching argument type
program example42;
class base1;
function bit showit (arg1_t i1);
$display ("\n\n %m: i1=%0d \n\n", i1);
endfunction
endclass
**VALID**
argument direction DOES
class ext1 extends base1; NOT match
function bit showit (output arg1_t i1);
$display ("\n\n EXT: %m: i1=%0d \n\n", i1);
return(0);
endfunction
endclass
base1 b1 = new();
ext1 e1 = new();
bit status;
arg1_t dummy;
initial begin
status=b1.showit(25);
status=e1.showit(dummy);
end
endprogram
Example 42 - Valid - Non-virtual method overrides another method with non-matching argument direction
program example43
class base1;
function bit showit (arg1_t i1);
$display ("\n\n %m: i1=%0d \n\n", i1);
endfunction
endclass
**VALID**
Number of arguments
class ext1 extends base1; DOES NOT match
function bit showit (arg1_t i1, i2=55);
$display ("\n\n EXT: %m: i1=%0d i2=%0d \n\n", i1, i2);
return(0);
endfunction
endclass
base1 b1 = new();
ext1 e1 = new();
bit status;
arg1_t dummy;
initial begin
status=b1.showit(25);
status=e1.showit(33);
end
endprogram
Example 43 - Valid - Non-virtual method overrides another method with different number of arguments
program example44;
class base1;
function bit showit (arg1_t i1);
$display ("\n\n %m: i1=%0d \n\n", i1);
endfunction
endclass
**VALID**
Return type DOES NOT
class ext1 extends base1; match
function logic showit (arg1_t i1);
$display ("\n\n EXT: %m: i1=%0d \n\n", i1);
return(0);
endfunction
endclass
base1 b1 = new();
ext1 e1 = new();
bit status;
arg1_t dummy;
initial begin
status=b1.showit(25);
status=e1.showit(33);
end
endprogram
Example 44 - Valid - Non-virtual method overrides another method with different return type