system verilog object oriented programming

Keywords: Verilog systemverilog

Class method

A program in a class is also called a method, that is, an internal task or function defined within the scope of the class. The following example defines the display () method for the Transaction class. System Verilog will call the correct display () method according to the type of handle.

class Transaction;
	bit[31:0]addr,crc,data[8];
	function void display();
		$display("@%0t:TR addr=8h,crc=sh",Stime,addr,crc);
		$write("\tdata[0-7]=");
		foreach(data[i])$write(data[i]);
		$display();
	endfunction 
endclass

initial begin 
	t=new();//Create a Transaction object
	t.display();//Method calling Transaction
end

Methods in the class use automatic storage by default, so you don't have to worry about forgetting to use the automatic modifier.

Define methods outside the class

In System Verilog, you can put the prototype definition (method name and parameters) of the method inside the class, and the program body (procedure code) of the method is defined after the class.
The following is an example of how to create an out of block declaration. Copy the first line of the method, describe the method name and parameters, and then add the keyword extern at the beginning. Then move the whole method to the back of the class definition, and add the class name and two colons (:: scope operator) before the method name. The class in the above example can be defined as follows.

//
class Transaction; 
	bit[31:0]addr,crc,data[8]; 
	extern function void display(); 
endclass 

function void Transaction::display(); 
	$display("@% 0t:Transaction addr=%h,crc=8h", Stime,addr,crc); 
	$write("\tdata[o-7]="); 
	foreach (data[i])Swrite(data[i]);
	$display();
endfunction

Note: there are two common errors:
       1. It is a common coding error that the prototype definition of a method does not match the content. System Verilog requires that except for one more class name and scope operator, the prototype definition is consistent with the method definition outside the block.
       2. Another common mistake is to forget to write the class name when declaring a method outside the class. As a result, its scope is one level higher. When a task tries to access class level variables and methods, the compiler will report an error.

Scope rule

A scope is a code block, such as a module, a program, task, function, class, or a begin end block. A for and foreach loop automatically creates a block, so the subscript weight can be declared and created as a local variable of the loop scope.
A new feature in system Verilog is that variables can be declared in a begin end block without a name, such as defining index variables in a for loop
The class should be defined in a package outside the program or module. This should be observed by all test platforms. Temporary variables can be defined somewhere in the innermost part of the test platform.
If an undeclared query is used in a block and there happens to be a variable with the same name in the block, the class will use the variable in the block without giving any warning.

The following example moves the class to a package, so the class can't see the program level variables, so it won't call it unintentionally.

//Move the class into package to find program errors
package Mistake;
	class Bad;
		logic[31:0]data[];
		
		//i is not defined and will not be compiled
		function void display;
			for(i=0;i< data.size();i++)
			$display("data[%0d]=%x",i,data[i]);
		endfunction 
	endclass 
endpackage

What is this

When using a variable name, SystemVerilog will first look in the current scope, and then look in the upper scope until the variable is found. But what if you want to explicitly reference class level objects in the deep underlying scope of a class. In the following example, "this" assigns oname to the class level variable oname

//Use this pointer to point to class level variables
class Scoping;
	string oname;

	function new(string oname);
		this.oname=oname;//Class variable oname = local variable oname 
	endfunction 
endclass

Use another class in one class

By using a handle to an object, a class can contain an instance of another class. This is like in Verilog, including an instance of another module within one module to establish the hierarchy of the design. The purpose of such inclusion is usually to reuse and control complexity.

Understanding dynamic objects

Passing objects to methods

When passing an object to a method, you may need to read the value in the object and modify the value of the object. In either case, when calling a method, you pass the handle of the object rather than the object
When calling a method with a scalar variable (not an array or an object) and using the ref keyword, SystemVerilog passes the address of the scalar, so the method can also modify the value of the scalar variable. If the ref keyword is not used, System Verilog copies the value of the scalar into the parameter variable. Any change to the parameter variable will not affect the value of the original variable.

//Transfer the packet to a 32-bit bus
task transmit(Transactiont);
	CBbus.rx data<=t.data;
	t.stats.startT=$time;
	...
endtask 

Transaction t;
initial begin 
	t=new();		//Allocate space for objects
	t.addr=42;		//Initialization value
	transmit(t);	//Passing objects to tasks
end

In the above example, the initialization block first generates a Transaction object and calls the transmit task. The parameter of the transmit task is the handle to the object. By using handles, transmit can read and write values in objects. However, if transmit tries to change the handle, the initialization block will not get the result because the ref modifier is not used on the parameter. (just as ref passes other function parameters)

This note is compiled with reference to the green paper system verilog verification. It is only for learning and experience exchange. If infringement is involved, please inform me and I will deal with it as soon as possible.

Posted by slands10 on Mon, 08 Nov 2021 02:38:44 -0800