Sei sulla pagina 1di 33

Object-Oriented Programming basics

1) Classes – A class is a group of members (data, subroutines). The data members are called
properties and the sub-routines are called methods. The sub routines operate on the data
members of the class.

Example

/////////////////////////
class abc;

bit [7:0] a;
bit [8:0] b;
integer status;

function new();
a = 8’h0;
b = 9’h1FF;
status = 1’b0;
endfunction

task clean();
a = 8’h0;
b = 9’h0;
status = 1’b0;
endtask

task xyz();

endtask

endclass

function integer check_status ();

endfunction

//////////////////////

Note:

a) A class in SV can be defined anywhere (program, module, package or anywhere


outside)
b) new() -> class constructor not to be confused with new[] -> dynamic array initial
size

2) Objects – An object is an instance of a class.


For example, if we use the same class above

abc a; //Creates an object handle of class abc.


a = new; //Create the object (memory allocated)

‘a’ is just a variable of class abc. The object is actually created with the new function.

Un-initialized object handles are initialized to null.

///////////////////////////////

task xyz (abc a)


if(a == null) a = new; //create an object if the handle has not been initialized till then
--------
--------
--------
endtask

////////////////////////////////

Object’s properties are called by using the ‘.’ Operator between the object handle and the
members

/////////////////////////////////

integer b1;
abc a1;
a1 = new;

a1.a = 10;
b1 = a1.check_status; //Not check_status(a1).

//Tasks are called like a1.xyz. They don’t return a value.

////////////////////////////////

Note(s):
a) Accessing static or virtual data members via a null object handle is illegal.
b) A net data type cannot be used as a class property (dynamic assignment on a net is
meaningless). Other than that, data member can have any data type.
c) Each method is free to access the members of its own instance

3) Constructors

Object is created when new (new function is the class constructor) is called.

Note(s):
a) ‘new’ function is non-blocking.
b) There is no return type for a new function (The LHS defines the return type of the
new function when it is called, as in a = new ;)
c) It is possible to pass arguments to the new constructor
d) Every class has a default new constructor (if not explicitly declared), which plainly
calls the new constructor of its immediate parent class (like super.new). It should be
fine even if a class doesn’t have a constructor (and no parent class), in which case the
default constructor assigns default values to all the properties of the class (X for
register, 0 for real, etc).
e) It is not mandatory for a class constructor to have the name ‘new’

Example 1:

Triangle t1 = new();
Triangle t2;

t2 = t1;

In the above case, one object gets created and two handles to the same object are created.

Example 2:

Triangle t1 = new;
Triangle t2 = new t1;

Here, a copy of t1 is made and copied into t2. Shallow copy happens. All properties are
copied, except the objects, in which case only the object handles are copied.

4) Garbage collection is automatic (SV has a methodology using which it de-allocates the
memory for various objects).

SV keeps track of handles and thereby frees the objects pointed by handles previously. In
simple terms, when a new is called and if the object handle (on the LHS of the new) has
been pointing to an object till then, that memory is cleared. Objects are cleared as and
when there is no object handle pointing to it.

Note:
a) During the simulation, the same object handle can point to different objects

5) Static members

Members inside class can be made static => all instances of that class have the same
members. Useful when the same version of a member has to be used across all the
instances of the same class

static integer a; //inside a class definition

static function xyz ();


------
endfunction

Note(s):
a) A static method cannot access non-static members (methods, properties) of a class.
b) A static method cannot have a “this”.
c) By default classes are ‘automatic’

6) ‘this’ -> a keyword used to access members of the current instance of a class. Part of
class definition (inside a function or a task). It is to be used only in non-static methods.

function xyz (integer x);


this.x = x;
endfunction

7) ‘super’ -> Used to refer to the members of the parent class. It is obvious that the member
being accessed in the parent class is overridden in the child class.

Here, ‘delay’, ‘value’ are overridden in the child class. The definition uses the
definition of ‘delay’ in the parent class (using ‘super’). 2 levels higher is not allowed
(super.super.value)

When using super with new, super.new should be the first executable statement in the
constructor.

8) Assignment, Renaming and Copying


If we assume packet as a class name,

packet p1; //Create an object handle


packet p2; //Create another object handle
p1 = new; //Create an object
p2 = new p1; //Create another object.

In the last line of code, an object p2 is created. P2’s properties are copied from p1. This is
called shallow copy of objects. If the class ‘packet’ has an object created (instance of
some other class + new), that object is not copied into p1. That will become a common
object across all the instances. The following example explains this.
If one feels the need to copy everything (including the nested objects), they need to use
the copy function, as in the code below.

///////////////////////////////////
packet p1;
packet p2;
p1 = new;
p2.copy(p1);

////////////////////////////////////

9) Inheritance
////////////////////////////////////
class parent;

integer a,b;

function new();

endfunction

task abc();

endtask

endclass

class child extends parent;


//The child class has all the members of the parents class, as if they were declared
inside //the child class. Additionally, they can have members specifically.
endclass

/////////////////////////////////////
Note(s)

a) Without using ‘extend’, the child class can as well (non-elegantly) instantiate the
parent class within itself.
b) In SV, classes can be derived only from one parent class.
c) The parents methods can be overridden (given a different definition) in the child
classes.

10) Overridden members

Sub-class objects are legal representatives of their parent objects.

11) When a sub – class in instantiated, the new method is invoked. The first thing that a new
function does in to invoke the new function of its base/parent class. This is because the
base class must be initialized before the child class. If the user doesn’t do this, the
compiler will insert a super.new automatically.

12) Data hiding.

In SV, members are Public, by default (they are available to anyone who have access to
the object’s name).

Members identified as ‘local’ are available only to methods inside the same class (could
be non-local methods also). These members are not visible even to the derived classes.
Non-local methods that use local methods and/or properties are visible in the derived
classes. Even if some one has the object handle, they will not be able to access the local
members of a class.

Within the same class, the local members are visible, even if they belong to different
instances
Here, other.i belongs to a different instance of the same class. As it is in the same class,
local member (‘i’) is visible here.

A ‘protected’ member has all the properties of a ‘local’ member, except that it can be
visible in the derived classes.

13) Const properties

Class properties can be made read-only by making them ‘const’.

Global constants (static) -> Value assigned in the class definition (at the time of declaring
the variable)

const int max_size = 1024;

Instance constants (dynamic) -> Value not assigned (at the time of declaring the variable)

const int max_size; //Value is assigned in the corresponding new.

14) Abstract classes

A base class can be made virtual (abstract), just because it is not intended to be
instantiated. An abstract class may as well have virtual methods. Virtual methods provide
prototypes for the derived classes.
Note(s)
a) A virtual method can be overridden in the derived class
b) If the sub-class doesn’t override all the methods of the virtual base class, it has to
become abstract (virtual).
c) An abstract class cannot be instantiated. It has to be derived.
d) Normal classes can also have virtual methods.

15) Out of block declaration (::)

If it is required to keep the method definition outside the class, we use the :: (scope
resolution operator).
-> Use the ‘extern’ keyword to mention that the definition of the method is outside the
‘class’ block

16) Parameterized classes

class abc #(parameter int size = 1);

endclass.

17) A simple example


18)
SV Introduction – Data types

1) Logic

a) Similar to ‘reg’ of verilog. ‘reg’ declaration in verilog will not


always infer a hardware register. To differentiate this (reg inferring a
register and not inferring a register), SV has another data type called
logic.
b) It cannot be driven by multiple drivers (can’t be used for inout
buses)
c) It can be driven both by continuous and procedural assignments
d) It can be used to connect 2 ports (hence, even for gate
instantiations)
e) 4-state.

2) ‘reg’ and ‘wire’ are 4 state variables (0, 1, x and z). SV has several 2 state
variables for improved simulator performance. The following table shows
various 2-state variables in SV

Please note that bit [7:0] a1 is not equivalent to byte a1 (signed and
unsigned)

3) $isunknown(a) returns a 1 if any bits of the expression ‘a’ is ‘x’ or ‘z’.

4) Fixed sized arrays

a) Declaration

int lo_hi [0:15]; //verilog style


int c_style[16]; //c style
int a[3:0] [15:0]; //multi-dimensional array

b) Note(s) – SV stores data @ long word (32-bit) boundaries. So, a


declaration like bit [7:0] a [3] creates 24-bits of unused space (4
times). Similarly, longint is stored in 2 long words.

c) Array initialization (use apostrophe and curly braces)


d) Special tasks/functions/constructs

i) $size(<array_name>) returns the size of the array in terms of


the number of elements

ii) foreach (a[i]) or foreach (a[i,j]) are used to iterate along the
arrays
iii) Aggregate copy and compare are allowed. Element wise
copy and compare also allowed. Aggregate arithmetic
operation not allowed.

5) Packed and unpacked arrays

a) Packed arrays - bit [7:0] [3:0] bytes. Here, ‘bytes’ is a variable


which can be accessed in part or as a whole (bytes = 32’hdead_beef is
allowed), Packed arrays are stored in contiguous locations. There is no
unused memory space like in unpacked arrays.
b) Unpacked arrays – bit [7:0] [3:0] bytes [3]. Here, the dimension
(3) is specified after the name. This makes the variable ‘bytes’ unpacked,
which means that the variable. Here, the third dimension is unpacked.
With a single sub-script ([2]), we can access a long word. With 2 sub-
scripts ([2] [0]), we can access a byte. With 3 sub-scripts, we can access
a bit.

6) Dynamic arrays

a) Declaration – done using [].


int a [];

b) Example

c) Note(s)

i) $size is valid as in the fixed size arrays


ii) Use dynamic arrays when we don’t know the array size up-front.
iii) Delete and size are the specialized routines for dynamic arrays
iv) A dynamic array can be assigned to a fixed size array if they have
the same number of elements
v)If a fixed array is assigned to a dynamic array, SV calls the new []
constructor internally.

7) Queues – Allow PUSH/POP from both the ends of the queue


a) Declaration
b [$] = {3, 4};
q [$] = {0, 2, 5};

b) Examples

c) Special tasks

i) insert (position, element); // Position starts from 0.


j) delete (position); //Position starts from 0
k) push_front(element);
l) push_back(element);
m) pop_front
n) pop_back

d) Note(s)

i) No need to call new [] for queues.


j) We can copy the contents of a fixed/dynamic array into a queue.

8) Associative arrays – Used for non-standard indices (widely spread memory


addresses)

a) Declaration
logic [63:0] a [*];

b) Example
c) first (get the first index), next (get the next index from here), prev (get
the previous index), delete (delete an element or the entire array), exists
(to find if an element at an id exists) are the specialized tasks.

9) Structures – Same data type


.

Unions – Different data types

10) User defined data types – typedef

11) Enumeration
Example

12) String data types

string abc = “Hello\n”;

If not initialized, abc will get initialized to “ “;

13) Event data types

Declaration: event abc;


Trigger: -> (blocking) or ->> (non-blocking)
Wait for an event either using @ or the ‘wait’ construct.

14)
Constraint-Random Verification

1) Declare a class with random data members (using rand or randc modifiers).
Specify the required constraints (limit the random value generation) and the
constraint solver calculates the required random number at the run time.

2) ‘rand’ creates random numbers. ‘randc’ tells the constraint solver to generate
a random number only once in every iteration (the next time the same
random number is generated only after all the possible numbers are randomly
generated)

3) Note that a constraint is defined in a {} block and not a begin…end block,


which is used for procedural blocks only

4) The ‘randomize’ function is an in-built function that returns a 1 if a solution


for the constraints is found. It returns a ‘0’ if the constraint solver fails to find
out a solution (in the form of a randomly generated value) for any random
variable with the given constraints

5) A constraint random test need not give the same results on different tools or
even different versions of the same tool (the CRS implementation is purely
vendor specific). But, with a given seed, the test has to give same results on
the same tool on different runs.

The constraint solver looks at all the constraints simultaneously. The random
values generated will have to satisfy all the constraints.

If no variable in a class is rand or randc, randomize on a constraint will fail.

6) Constraint examples

Expressions are separated by a ‘;’.


a) Relational constraints

Only one relational operator is allowed per expression (0<a<b will not
work)

constraint a {0<a;
a <=10;
b >= 4;
}

b) ‘inside’ specifier
a inside {0, [2:10], [90:100]};
!( a inside {0, [2:10], [90:100]}); // Any where, but in these ranges
( a inside {0, 1, 1, 1}); // All 4 elements. Probability of 1 is ¾

c) ‘dist’ operator for weighted distributions – A ‘dist’ operator has values


and weights separated by := or :/ operators.

a dist {0:=40, [1:3]:=60};


-> 0 has a weight of 40/220, 1 to 3 have a weight of 60/220.

a dist {0:/40, [1:3]:/60};


-> 0 has a weight of 40/100, 1 to 3 have a weight of 20/100.

d) Implication operator.

constraint c {
(a) -> b inside {[1:3]}; // If a occurs, ‘b’ in that range
}
We can also use if-else inside the constraint blocks.

Example
If the in the above example, there is another constraint y >0, it will make
the implication as bi-directional. That will mean that both y and x can
never be zeros. This is leave us with only 3 possibilities for x and y all
having probabilities of 1/3

We can use the solve….before constraint to define the order in which


variables have to be solved.

This will have the same probabilities as the one in the table above.

e) Arithmetic operations

a % 2 inside {1, 2, 3} ;

7) A constraint can be switched off before calling the randomize function using
the constraint_mode function
<class instance or object name> DOT <constraint name> DOT
constraint_mode (0);

If the <constraint name> above is not mentioned, all the constraints are
switched OFF.

8) Constraints can be over-ridden dynamically using the randomize () with


function call
9) SV has two void functions pre_randomize() and post_randomize(). These
may be required before and after randomize(). For example, if after
randomize(), we want to print certain values (we use post_randomize()).

10) Rand Case

11) We can call the srandom(seed) in an object’s new function to specify the
seed for the RNG.

12)
Scheduling semantics

1)
Threads, Synchronization and IPC

1) Semaphores

SV’s built-in class for mutual exclusion (similar to mutexes in operating systems). It is
conceptually a bucket of keys. Threads need the keys to access resources. They may be
kept in a blocking way, waiting till a key is available. Multiple blocking threads are
queued in a FIFO order.

When a semaphore is allocated, a bucket with a fixed number of keys is created.


Processes/threads need to procure keys to access resources.

semaphore abc; // create a semaphore.

Semaphore is an in-built class that has the following methods


a) new
function new (int KeyCount = 0); // Number of keys, default is 0. More keys can
be created, if required.
b) put
task put (int KeyCount = 1);
-> Used to return keys to the semaphore. If a process is waiting to access a
resource, and if the required numbers of keys have been returned, it will be able to
access the resource. Default number of keys is 1.
c) get
task get (int KeyCount = 1);
-> Used to get the specified number of keys from the semaphore. Default is 1.
If the keys are unavailable, the process blocks.
d) try_get
function int try_get (int KeyCount = 1);
-> to procure keys without blocking
Note: If there is only one key available, and first a thread requests for two keys and then a
second thread requests for one key, the second thread doesn’t win the available key (FIFO
ordering)

2) Mailboxes

Built-in classes for passing objects between processes. Mail box size can be bounded or
unbounded.

mailbox abc; //Create a mailbox

Only object handles are posted into the mailboxes (not objects). So, the objects can be
changed after they are posted and before they are de-queued (though it is not
suggested).

Mail box methods

a) new
function new (int bound = 0);
-> If the bound argument is 0 (which is the case, by default), the mailbox is
unbounded. Otherwise, it is bounded by the size mentioned.
b) put
task put (singular message);
-> To put messages into mailboxes. For both bounded and unbounded mailboxes.
In the case of bounded mailboxes, this process blocks.
c) try_put
function int try_put (singular message);
-> meaningful in the case of bounded mailboxes. Return and countinue (non-
blocking) if the mailbox is full (returns 0).
d) get
task get (ref singular message);

-> To get messages from a mailbox. Block until the requested data is available.
e) peek
task peek (ref singular message)
-> Copies a message from the mailbox, without removing it. It blocks till the
message is available.
f) try_get
function int try_get (ref singular message)
-> Try to get if the queue is non-empty. If the queue is empty, return zero and
proceed to the next statement. If there’s a type mismatch between the message
variable and the message in the mailbox, try_get returns -1.
g) try_peek
function int try_peek (ref singular message);
-> Return and continue if message is not available in the mailbox. If data is
available, copy (and don’t remove) the data. Return -1 if type mismatch. Return a 0
if no message.
h) num
function int num();
-> returns the number of messages in the mailbox
3) Parameterized mailboxes

Mailboxes can be made parametric to prevent run-time errors. This helps in detecting
type mismatches between the message posted and message in the mailbox (parameter
defines the type).

mailbox # (type = datatype)

The compiler ensures that all the get, put, try_get, try_put methods are compatible with
the type of the mailbox (all mismatches are caught @ compile time, not @ run time).

4) Events

In verilog events are triggered by -> operator. Processes wait for the events using the
@ operator.Verilog events do not have a time duration

Events are edge-sensitive.

event abc = null;


event xyz;

Triggering an event
-> Use the ‘->’ operator
-> An event trigger unblocks all the events currently waiting on that event.
-> Non – blocking events are triggered using the ‘->>’ operator

Calling an event
-> Use the @ operator
-> Block the calling process until the given event is triggered

Here, the initial block triggers the event e1 and waits on the event e2 (which gets fired
from another block)

The ‘@’ trigger is edge-sensitive. It is sometimes required to wait on levels. For this, we
need to use ‘wait (e2.triggered)’. If the event (for which a thread is waiting) is fired in the
same time step as the one in which the ‘@’ thing is fired, there could be an issue and the
thread waiting could get blocked for ever (as it could miss the edge). To get over this, we
use the wait construct (as it is level sensitive)
If you replace ‘wait’ with ‘@’ in the above example, you will not see the last line of the
output above.

An event can be passed as an argument to a function.

5) Threads (begin – end => things inside run sequentially, fork – join* => things inside run in
parallel)

6) fork – join
7) fork – join_none
8) fork – join_any

9) Disabling threads (use ‘disable’ construct)


In short, make the blocks (fork – join* or begin – end) ‘named’ and use disable
followed by the name of the block to disable the block

10)
Verification Fundamentals

1) A generic architecture

2) A Transaction is the definition of an activity that can occur in a design in a


period of time. A Transactor is that component of a TB that creates
transactions. For example, if a control signal is high, the data input to a block
should get the data for one cycle. This can be a transaction.

3) A driver, like the transactor is an active component (its behavior


defines/alters the behavior of the DUT). A driver is that component of a TB
that converts transactions in to pin level activity. In simpler terms, it takes the
transactions and drives the RTL/DUT pins

4) A Responder is like a driver, except that it responds to some activity on the


pins of the DUT. The driver, on the other hand, creates some activity on the
pins

5) A monitor is a component that typically logs the activity on the DUT pins.

6) A generator is a component that generates a stream of transactions for the


DUT. This stream could be directed, random, constrain-random.

7) A master is a bi-directional component that is similar to the generator. It


creates requests, gets responses, creates transactions, waits for responses and
decides its next course of action. A slave on the other hand responds to
requests (it is also bi-directional)

8) The TB also has components for the analysis/report of the activity in the
entire system.
The scoreboards/checkers are the components which keep track of activity
going into and out of the DUT and thereby analyze the status of the DUT
(Pass/Fail status, for example). They have means to generate the expected
data against which they compare the actual data coming out of the DUT for a
particular transaction.

A coverage collector is another component for the analysis. They give a


numerical analysis of things – how many times an event occurred, how many
times a line in a code has been covered, etc

9)
Advanced Verification Methodology or AVM

1) It is a set of base classes and utilities to build test-benches

2) AVM Named component – The avm_named_component is a base class in


AVM. This is used to construct testbenches as a network of components.
This class extended, creates a class name and top level hierarchy for all the
named components

3) AVM-Threaded component – It is a derived class of


avm_named_component. It provides a place to create a separate thread of
execution. Components like stimulus generators extend the
avm_threaded_component as they need a separate thread of execution.

Each class derived in from the threaded_component base class, typically has
a run() task. All the run() tasks are fired as separate threads (dynamically
fired or forked) once the simulation is started.

4) Class based components in the AVM communicate through transaction level


ports and exports. AVM provides ports (avm_blocking_put_port, for
example) for the communication between two transaction level components.

5) The environment is the top level container of a TB. It holds the top level
components in the hierarchies of the avm_named_components and it
oversees the TB execution. The base class for environments is avm_env,
which is derived from the avm_named_component.

6) Message tasks are avm_report_message(), avm_report_warning(),


avm_report_error(), avm_report_fatal(). The messages under these tasks are
grouped and cumulatively reported at the end of the simulation

7)
8)
Miscellaneous

1) Packages

In Verilog, there is no efficient way to accommodate variables,


functions, etc in a global way (to be used across various modules).
People try to do it non-elegantly by using `include. To overcome
this, SV has Packages.

Packages are defines between ‘package’ and ‘endpackage’ key


words.

A Package can contain any or all of the following

 Parameter declarations
 Function/Task definitions
 User defined data types.
 Constant variable definitions
 Import statements from other packages.

Note:

e) In a Package, parameter definition cannot to overridden (equivalent to


a localparam)
f)
2)

11) Ports, binds, packages, interfaces, program


12) Scheduling semantics
13) Tasks and Functions
14) Clocking domains
15) SV for design
16) SV papers, key points
Q and A
1) There is a parent class which is inherited by a child class. The parent class
constructor has an argument. If in the child class we don’t use the
super.new(arg), what will happen?

It gives an error like “Super class constructor has non-default arguments.


Arguments can be specified in the “extends” clause or by calling the
super.new() explicitly.

2) What is the advantage of interfaces in system verilog?


3) What are virtual interfaces in SV?
4) What is a package in SV?
5) What are always_comb, always_latch, always_seq in SV
6) What are unique and priority keywords in sv?
7) How do we control a parameter from command line in SV
8) What is call back in SV?
9) What is the need of clocking blocks in SV?
10) Are signals inside an interface, wire or logic?
11) If randomization fails, what will be the values of the corresponding
(rand/randc) variables?
12) What is inheritance?
13) What is polymorphism, give an example
14) What is the difference between a deep copy and a shallow copy in SV?
15) What is a bind statement?
16) What is the difference between a mailbox and a queue in SV?
17) What is the difference between static and non-static properties of a class?

Static properties are commonly shared by all the instances of the same class,
whereas non-static are not common, they change from instance to instance.

18) Difference between overloading and overriding?


19) What are $cast, $root and $unit tasks?
20) What is a final block in SV?

It is the opposite of initial. It gets executed just before the end of simulation.
There cannot be any delay elements in this block

21) Code coverage VS Functional coverage? What it signifies if one of them is


more than the other?

22) Why is always block not allowed in a program block

23) What is ‘alias’ keyword in SV?

alias a = b; means that if one of them changes, the other also changes

24) What is the difference between static task abc(); and task static abc();
25) What is the difference between ‘int’ and ‘integer’ in SV?
int is 2-state, 32-bit signed quantity. ‘integer’ is something taken over from
Verilog. It is a 4-state variable, 32-bit signed

26) What is the difference between ‘.’ and ‘::’?

‘.’ refers to the member of an object (instance of a class), where as the scope
resolution operator, ‘::’, refers to the member of the class itself.

27)

Potrebbero piacerti anche