Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
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
endfunction
//////////////////////
Note:
‘a’ is just a variable of class abc. The object is actually created with the new function.
///////////////////////////////
////////////////////////////////
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).
////////////////////////////////
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
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.
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.
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
/////////////////////////////////////
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.
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.
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.
Global constants (static) -> Value assigned in the class definition (at the time of declaring
the variable)
Instance constants (dynamic) -> Value not assigned (at the time of declaring the variable)
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.
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
endclass.
1) Logic
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)
a) Declaration
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.
6) Dynamic arrays
b) Example
c) Note(s)
b) Examples
c) Special tasks
d) Note(s)
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.
11) Enumeration
Example
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)
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.
6) Constraint examples
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 ¾
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
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.
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.
2) Mailboxes
Built-in classes for passing objects between processes. Mail box size can be bounded or
unbounded.
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).
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).
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
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.
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
10)
Verification Fundamentals
1) A generic architecture
5) A monitor is a component that typically logs the activity on the DUT pins.
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.
9)
Advanced Verification Methodology or AVM
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.
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.
7)
8)
Miscellaneous
1) Packages
Parameter declarations
Function/Task definitions
User defined data types.
Constant variable definitions
Import statements from other packages.
Note:
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.
It is the opposite of initial. It gets executed just before the end of simulation.
There cannot be any delay elements in this block
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
‘.’ 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)