How many parallel processes does this code generate?
fork
for (int i=0; i < 10; i++ ) begin
ABC();
end
join
Since the “for” loop is inside the fork join, it executes as a single thread.
Which keyword in SystemVerilog is used to define Abstract classes?
Sometimes a class is defined with an intention to be only a base class from which other classes can be derived. Methods may also be defined as virtual in an abstract class without any definition. Such a base class with no intention to create an object is defined as an abstract class and is identified using the virtual keyword as prefix in the class definition.
For Example:
virtual class A;
virtual function process();
endclass: A
What is the difference between a virtual function and a pure virtual
function in SystemVerilog?
A function in a class is defined as virtual to allow overriding the implementation of the function in a derived class. The base class may or may not have an implementation of the function that is virtual and may or may not be overridden in the derived class. A pure virtual function is a kind of virtual function which will have only declaration without any implementation. Any class that derives from a base class having “pure virtual” functions need to implement the function. Pure virtual functions are normally used in abstract class definitions. See the following example of usage of same.
virtual class BasePacket;
// No implementation
pure virtual function integer send(bit[31:0] data);
endclass
class EtherPacket extends BasePacket;
virtual function integer send(bit[31:0] data);
// body of the function
// that implements the send
….…
endfunction
endclass
What does keyword “extends” represent in SystemVerilog?
The “extends” keyword is used in class definition to specify the class from which the class is derived. For Example: class A extends B; means class A is derived from class
What are Semaphores? When are they used?
Semaphore is a mechanism used to control access to shared resources. It can be considered like a bucket with a number of keys created when the semaphore is created. Multiple processes that use a semaphore to access a shared resource should first procure a key from the bucket before they can continue to execute. This guarantees that processes which do not get a key will wait until the ones that procured keys releases them back. Semaphores are typically used for mutual exclusion, access control to shared resources, and basic
synchronization. Following is how a semaphore can be created.
semaphore smTx;
smTx = new(1); //create the semaphore with 1 keys.
The methods get() (blocking call) and try_get() (nonblocking call) are used to get keys
from semaphore while put() method is used to release keys back.
What are Mailboxes? What are the uses of a Mailbox?
A mailbox is a communication mechanism that allows messages to be exchanged between processes. Data can be sent to a mailbox by one process and retrieved by another. Following is an example of declaring and creating a mailbox:
mailbox mbxRcv;
mbxRcv = new();
To place a message in a mailbox, two methods are supported put() (blocking) and peek()
(nonblocking). To retrieve a message from mailbox, two methods are supported get() (blocking) and try_get() (nonblocking). To retrieve the number of messages in the mailbox, we can use num().
. What is difference between bounded and unbounded mailboxes? How
can we create unbounded mailboxes?
A mailbox is called bounded if the size of mailbox is limited when created.
mailbox mbxRcv;
mbxRcv = new(10); //size bounded to 10
A mailbox is unbounded if the size is not limited when created.
mailbox mbxRcv;
mbxRcv = new(); //size is unbounded or infinite
A bounded mailbox becomes full when it contains the bounded number of messages and any further attempt to place a message will cause the process to be suspended while unbounded mailboxes never suspend a thread in a send operation
What is an “event” in SystemVerilog? How do we trigger an “event” in
SystemVerilog?
An identifier declared as an event data type is called a named event. Named event is a data type which has no storage. A named event can be triggered explicitly using “->” operator. A process can use the event control “@” operator to block execution until the event is triggered. Events and event control gives a powerful and efficient means of synchronization between two or more concurrently running process. Following example pseudo code shows how two processes can synchronize execution using an event. The send_req() task emits an event once a request is send while the receive_response() event waits until req_send event is seen
module test;
event req_send;
initial begin
fork
send_req();
receive_response);
join
end
task send_req();
//create and send a req
-> req_send; //trigger event
endtask
task receive_response();
@req_send; //wait until a send event is triggered
//collect response
endtask
endmodule
What is std::randomize() method in SystemVerilog and where is it
useful?
The std::randomize() is a scope randomize function that enables users to randomize data in the current scope without the need to define a class or instantiate a class object. This is useful if some variables required to be randomized are not part of a class. Refer following example of a function inside a module. There are few variables inside a module that can
be randomized using std::randomize().
module stim;
bit [15:0] addr;
bit [31:0] data;
function bit gen_stim();
bit success, rd_wr;
success = std::randomize(addr, data, rd_wr);
return rd_wr ;
endfunction
…
endmodule
std::randomize() behaves similar to randomize() function of classes and can take all kinds of constraints supported in a class. For example if we want to add a constraint, it can be added using the with construct as follows:
success = std::randomize( addr, data, rd_wr ) with {rd_wr -> addr > ‘hFF00;};
What is a virtual interface and where is it used?
A virtual interface is a variable that points to an actual interface. It is used in classes to provide a connection point to access the signals in an interface through the virtual interface pointer. The following example shows an actual interface bus_if that groups a set of bus signals. A BusTransactor class then defines a virtual interface of this type that is used to access all signals from this bus_if for driving a request or waiting for a grant signal. The top level test module which instantiates the physical interface will pass the
handle of same to the BusTransactor class through constructor which gets assigned to the
virtual interface pointer.
interface bus_if; // A bus interface
logic req, grant;
logic [7:0] addr, data;
endinterface
class BusTransactor; // Bus transactor class
virtual bus_if bus; // virtual interface of type bus_if
function new( virtual bus_if b_if );
bus = b_if; // initialize the virtual interface
endfunction
task request(); // request the bus
bus.req <= 1‘b1;
endtask
task wait_for_bus(); // wait for the bus to be granted
@(posedge bus.grant);
endtask
endclass
module top;
bus_if bif(); // instantiate interfaces, connect signals etc
initial begin
BusTransactor xactor;
xactor = new(bif); //pass interface to constructor
end
endmodule
What is the concept of factory and factory pattern?
In object oriented programming, a factory is a method or a function that is used to create different objects of a prototype or a class. The different classes are registered with the factory and the factory method can create objects of any of the registered class types by calling the corresponding constructor. The method of creating objects instead of calling the constructor method directly is called factory pattern. Using factory based object creation instead of calling constructors directly allows one to use polymorphism for object creation. This concept is implemented in UVM (Universal Verification Methodology) base class library and is used for creating and overriding base class objects with derived class objects.
What is the concept of callback?
A “callback” is any function that is called by another function which takes the first
function as an argument. Most of the times, a callback function is called when some “event” happens. In a Verification testbench, this feature is useful for several applications:
1) Calling back a function to inject error on transactions sent from a driver
2) When a simulation phase is ready to end, calling a function to drain all pending
transactions in all sequence/driver.
3) Calling a coverage sample function on a specific event.
Most of the times, callback functions are implemented by registering them with a component/object that calls back on some defined conditions.
An example call back function in UVM is phase_ready_to_end() which is implemented in the base class and is registered with the UVM_component class. The function gets called when the current simulation phase is ready to end always. Hence, a user can implement any functionality that needs to be executed at end of a simulation phase by overriding this
function definition
What is a DPI call?
DPI stands for Direct Programming Interface and it is an interface between SystemVerilog and a foreign programming language like C/C++. DPI allows direct inter-language function calls between the languages on either side of the interface. Functions implemented in C language can be called in SystemVerilog (imported) and functions implemented in SystemVerilog can be called in C language (exported) using the DPI layer. DPI supports both functions (executing in zero time) and tasks (execution consuming time) across the language boundary. SystemVerilog data types are the only data types that can cross the boundary between SystemVerilog and a foreign language in either direction.
What is the difference between “DPI import” and “DPI export”?
A DPI imported function is a function that is implemented in the C language and called in the SystemVerilog code.
A DPI exported function is a function that is implemented in the SystemVerilog language and exported to C language such that it can be called from C language. Both functions and tasks can be either imported or exported.
What are system tasks and functions? Give some example of system
tasks and functions with their purpose.
SystemVerilog language supports a number of built-in system tasks and functions for different utilities and are generally called with a “$” prefix to the task/function name. In addition, language also supports addition of user defined system tasks and functions.
Following are some examples of system tasks and functions (categorized based on functionality). For a complete list, one should refer to LRM.
1) Simulation control tasks – $finish, $stop, $exit
2) Conversion functions – $bitstoreal, $itor, $cast
3) Bit vector system functions – $countones, $onehot, $isunknown
4) Severity tasks – $error, $fatal, $warning
5) Sampled value system functions – $rose, $fell, $changed
6) Assertion control tasks – $asserton, $assertoff
What is the difference between $rose and @ (posedge) ?
Ans: 1) $rose gives out an sampled boolean value by checking whether the signal had risen from previous edge(whatever is given) to the current edge. When you say $rose(a), it gives 1 or 0. Moreover $rose is set to one if the least significant bit of a changes from any value(0,x,z) to 1 else it is set to 0.
2) @posedge is an event.It is checked instantly.It does not return any value.
This is an event control that blocks a process waiting for an update to ‘a’ where the LSB goes from zero to non-zero.
$rose(a) is a sampled function that must be used in the context of some other synchronous event. It returns true if the LSB of ‘a’ was zero in the previous cycle and is now 1 ub the current cycle. Otherwise it returns false.
What is the Difference between param and typedef?
A parameter is defined by Verilog as a constant value declared within the module structure. The value can be used to define a set of attributes for the module which can characterize its behavior as well as its physical representation. Defined inside a module.
Local scope. Maybe overridden at instantiation time.
If multiple parameters are defined, they must be overridden in the order they were defined. If an overriding value is not specified, the default parameter declaration values are used.
Maybe changed using the defparam statement.
Typedef allows users to create their own names for type definitions that they will use frequently in their code. Typedefs can be very convenient when building up complicated array definitions