Q Ovm

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 44

(Q i40) What are the differences between vmm and ovm/uvm ?

(Q i41)What is the advantage of uvm agent ?


The uvm_agent virtual class should be used as the base class for the user-
defined agents. Deriving from uvm_agent will allow you to distinguish agents
from other component types also using its inheritance. Such agents will
automatically inherit features that may be added to uvm_agent in the future.

While an agent's build function, inherited from uvm_component, can be
implemented to define any agent topology, an agent typically contains three
subcomponents:
a driver, sequencer, and monitor. If the agent is active,

subtypes should contain all three subcomponents. If the agent is passive,
subtypes should contain only the monitor.

(Q i42)How multiple set_config_* are resolved at same hierarchy level and at different hierarchy levels ?
Configuration is a mechanism in UVM that higher level components in a hierarchy can configure the lower level
components variables. Using set_config_* methods, user can configure integer, string and objects of lower level
components. Without this mechanism, user should access the lower level component using hierarchy paths,
which restricts reusability. This mechanism can be used only with components. Sequences and transactions
cannot be configured using this mechanism. When set_config_* method is called, the data is stored w.r.t strings
in a table. There is also a global configuration table.
Higher level component can set the configuration data in level component table. It is the responsibility of the
lower level component to get the data from the component table and update the appropriate table.
Following are the method to configure integer , string and object of uvm_object based class respectively.


function void set_config_int (string inst_name,
string field_name,
uvm_bitstream_t value)

function void set_config_string (string inst_name,
string field_name,
string value)

function void set_config_object (string inst_name,
string field_name,
uvm_object value, bit clone = 1)
There are two ways to get the configuration data:
1)Automatic : Using Field macros
2)Manual : using gte_config_* methods.



Automatic Configuration:



To use the atomic configuration, all the configurable fields should be defined using uvm component field macros
and uvm component utilities macros.


(S)uvm component utility macros:
For non parameterized classes
`uvm_component_utils_begin(TYPE)
`uvm_field_* macro invocations here
`uvm_component_utils_end
For parameterized classes.
`uvm_component_param_utils_begin(TYPE)
`uvm_field_* macro invocations here
`uvm_component_utils_end

(S)Driver class Source Code:


Similar to driver class, all other components env, agent and monitor are define.


class driver extends uvm_driver;

integer int_cfg;
string str_cfg;

`uvm_component_utils_begin(driver)
`uvm_field_int(int_cfg, UVM_DEFAULT)
`uvm_field_string(str_cfg, UVM_DEFAULT)
`uvm_component_utils_end

function new(string name, uvm_component parent);
super.new(name, parent);
endfunction

function void build();
super.build();
endfunction

endclass

(S)Testcase:


Using set_config_int() and set_config_string() configure variables at various hierarchal locations.


//t_env.ag1.drv.int_cfg
//t_env.ag1.mon.int_cfg
set_config_int("*.ag1.*","int_cfg",32);

//t_env.ag2.drv
set_config_int("t_env.ag2.drv","int_cfg",32);

//t_env.ag2.mon
set_config_int("t_env.ag2.mon","int_cfg",32);

//t_env.ag1.mon.str_cfg
//t_env.ag2.mon.str_cfg
//t_env.ag1.drv.str_cfg
//t_env.ag2.drv.str_cfg
set_config_string("*.ag?.*","str_cfg","pars");

//t_env.str_cfg
set_config_string("t_env","str_cfg","abcd");


Manual Configurations:



Using get_config_* methods, user can get the required data if the data is available in the table.
Following are the method to get configure data of type integer , string and object of uvm_object based class
respectively.


function bit get_config_int (string field_name,
inout uvm_bitstream_t value)

function bit get_config_string (string field_name,
inout string value)

function bit get_config_object (string field_name,
inout uvm_object value,
input bit clone = 1)



If an entry is found in the table with "field_name" then data will be updated to "value" argument . If entry is not
found, then the function returns "0". So when these methods are called, check the return value.

Example:
(S)Driver class code:
class driver extends uvm_driver;

integer int_cfg;
string str_cfg;

`uvm_component_utils(driver)

function new(string name, uvm_component parent);
super.new(name, parent);
endfunction

function void build();
super.build();
void'(get_config_int("int_cfg",int_cfg));
void'(get_config_string("str_cfg",str_cfg));
uvm_report_info(get_full_name(),
$psprintf("int_cfg %0d : str_cfg %0s ",int_cfg,str_cfg),UVM_LOW);
endfunction

endclass

The method get_config_int searches a table of configuration settings for a field named "iterations" that is applicable to
the current instance. If a field of that name is found, the method sets the value of the second argument count to the
value of the "iterations" field and returns true, otherwise it returns false. In this case, if the configuration field is not found,
the driver gracefully reverts to using a default value.

Entries are created in the table of configuration settings by calling one of the three
methods set_config_int, set_config_string or set_config_object. Each entry consists of an instance name, a field
name and a value. Values set by set_config_int can be retrieved by get_config_int, and the same for the other field
types. Moreover, if there exists a field with a matching name, as created by the macro`ovm_field_int, then that field is
also set to the same value. The existence of fields as created by `ovm_field_int is not necessary for the operation of
the set_config_ / get_config_ methods, but such fields are set as a side-effect of executing set_config_.


(Q i43) Is it possible to connect multiple drivers to one sequencers ? if yes, then how ?
One way that you can do this is to use TLM peek and get. All drivers will call peek (instead of get_next_item); the last
driver that gets the item will call get to signify to the sequencer that this item is done. You will need some handshaking to
coordinate the activities between the drivers. For example, in driver #1:
task get_and_drive();
...
seq_item_port.peek(item); //TLM style equivalent to get_next_item()
@parent.driver2_done; //wait for driver2 to get same xaction
...
seq_item_port.get(item); //TLM style equivalence of item_done()
...
endtask
in driver #2 code:
task get_and_drive();
...
seq_item_port.peek(item); //TLM style
->parent.driver2_done; //signal to driver #1 that driver #2 is done with this xaction
...
endtask
Note also that you need to make sure that the drivers do not call peek at the same time; otherwise, the sequencer will
hang.
Create a high level driver component which contains the instantiations of driver1 and driver2 types.
From high level driver component run task request for the item using the get_next_item(), Once u receive the item pass it
to the driver1 and driver2 instantiations. In high level driver after transmitting item to both components wait for it to be
processed by both components. Once high level driver gets indication that item is processed, indicate the item_done to
sequencer.


(Q i44) What is the difference between factory and callbacks?
Callbacks and factories are two different approaches of solving the same problem - changing the behavior of your code
without modifying the original code. A callback can replace an individual virtual method whereas the factory potentially
overrides all virtual methods in the original class as a group. Callbacks have the advantage that you can dynamically
override callbacks individually, but have the disadvantage that they restrict what can be modified (which some might
consider an advantage).
"Callbacks are method calls placed inside your testbench components, which can be overriden by other components---
typically, a user testcase. This provides an easy mechanism for testcases to change the behavior of the verification
environment without actually modifying the testbench source code. Callbacks can be used to change a transaction's
randomization, the generation of data, add additional coverage terms, define custom scoreboard compare functions,
inject errors, or perform any test specific modifications need."

Callbacks and factories are two different approaches of solving the same problem - changing the behavior of your code
without modifying the original code. A callback can replace an individual virtual method whereas the factory potentially
overrides all virtual methods in the original class as a group. Callbacks have the advantage that you can dynamically
override callbacks individually, but have the disadvantage that they restrict what can be modified (which some might
consider an advantage). In my opinion, the factory can provide all the necessary functionality.

CALLBACK MECHANISM FOR OVM OBJECTS
This OVM callback package provides a callback mechanism for the OVM SystemVerilog library. The callback mechanism
allows you to attach callbacks (procedural extensions) to components and other OVM objects, and to execute those
callbacks in interesting places. This technology complements the OVM factory mechanism that enables unplanned
extensions for both procedural and structural elements.

The callback mechanism includes the following functionality and capabilities:
Attach callbacks to specific components and objects.
Manage the callback queue by prepending, appending or inserting callbacks.
Remove, enable or disable callbacks.
Refer to callbacks by name as well as by the callback's handle.
Execute callbacks inside the associated object, or from outside of the associated object.
Execute task-based callbacks in parallel or in sequence.
Trace all callback related activity.
List all callbacks on an object or in the verification environment.


ovm_factory
As the name implies, ovm_factory is used to manufacture (create) OVM objects and components. Only
one instance of the factory is present in a given simulation (termed a singleton). Object and component
types are registered with the factory using lightweight proxies to the actual objects and components
being created. The ovm_object_registry #(T,Tname) and ovm_component_registry #(T,Tname) class
are used to proxy ovm_objects and ovm_components.
The factory provides both name-based and type-based interfaces.
type-based The type-based interface is far less prone to errors in usage. When errors do occur,
they are caught at compile-time.
name-based The name-based interface is dominated by string arguments that can be misspelled
and provided in the wrong order. Errors in name-based requests might only be
caught at the time of the call, if at all. Further, the name-based interface is not
portable across simulators when used with parameterized classes.
ummary
ovm_factory
As the name implies, ovm_factory is used to manufacture (create) OVM objects and components.
CLASS DECLARATION
class ovm_factory

REGISTERING TYPES
register Registers the given proxy object, obj, with the factory.
TYPE & INSTANCE OVERRIDES
set_inst_override_by_type
set_inst_override_by_name Configures the factory to create an object of the overrides
type whenever a request is made to create an object of the
original type using a context that matches full_inst_path.
set_type_override_by_type
set_type_override_by_name Configures the factory to create an object of the overrides
type whenever a request is made to create an object of the
original type, provided no instance override applies.
CREATION
create_object_by_type
create_component_by_type
create_object_by_name
create_component_by_name Creates and returns a component or object of the
requested type, which may be specified by type or by
name.
DEBUG
debug_create_by_type
debug_create_by_name These methods perform the same search algorithm as the
create_* methods, but they do not create new objects.
find_override_by_type
find_override_by_name These methods return the proxy to the object that would
be created given the arguments.
print Prints the state of the ovm_factory, including registered
types, instance overrides, and type overrides.
USAGE Using the factory involves three basic operations

register
function void register ( ovm_object_wrapper obj )

Registers the given proxy object, obj, with the factory. The proxy object is a lightweight substitute for
the component or object it represents. When the factory needs to create an object of a given type, it
calls the proxys create_object or create_component method to do so.
When doing name-based operations, the factory calls the proxys get_type_name method to match
against the requested_type_name argument in subsequent calls
tocreate_component_by_name and create_object_by_name. If the proxy objects get_type_name
method returns the empty string, name-based lookup is effectively disabled.

set_inst_override_by_type
function void set_inst_override_by_type ( ovm_object_wrapper original_type,
ovm_object_wrapper override_type,
string full_inst_path )

set_inst_override_by_name
function void set_inst_override_by_name ( string original_type_name,
string override_type_name,
string full_inst_path )

Configures the factory to create an object of the overrides type whenever a request is made to create an
object of the original type using a context that matchesfull_inst_path. The original type is typically a
super class of the override type.
When overriding by type, the original_type and override_type are handles to the types proxy
objects. Preregistration is not required.
When overriding by name, the original_type_name typically refers to a preregistered type in the
factory. It may, however, be any arbitrary string. Future calls to any of the create_* methods with the
same string and matching instance path will produce the type represented by override_type_name, which
must be preregistered with the factory.
The full_inst_path is matched against the contentation of {parent_inst_path, ., name} provided in
future create requests. The full_inst_path may include wildcards (* and ?) such that a single instance
override can be applied in multiple contexts. A full_inst_pathof * is effectively a type override, as it will
match all contexts.
When the factory processes instance overrides, the instance queue is processed in order of override
registrations, and the first override match prevails. Thus, more specific overrides should be registered
first, followed by more general overrides.

set_type_override_by_type
function void set_type_override_by_type ( ovm_object_wrapper original_type,
ovm_object_wrapper override_type,
bit replace = 1 )

set_type_override_by_name
function void set_type_override_by_name ( string original_type_name,
string override_type_name,
bit replace = 1 )

Configures the factory to create an object of the overrides type whenever a request is made to create an
object of the original type, provided no instance override applies. The original type is typically a super
class of the override type.
When overriding by type, the original_type and override_type are handles to the types proxy
objects. Preregistration is not required.
When overriding by name, the original_type_name typically refers to a preregistered type in the
factory. It may, however, be any arbitrary string. Future calls to any of the create_* methods with the
same string and matching instance path will produce the type represented by override_type_name, which
must be preregistered with the factory.
When replace is 1, a previous override on original_type_name is replaced, otherwise a previous override,
if any, remains intact.

CREATION
create_object_by_type
function ovm_object create_object_by_type ( ovm_object_wrapper requested_type,
string parent_inst_path = "",
string name = "" )

create_component_by_type
function ovm_component create_component_by_type (
ovm_object_wrapper requested_type,
string parent_inst_path = "",
string name,
ovm_component parent
)

create_object_by_name
function ovm_object create_object_by_name ( string requested_type_name,
string parent_inst_path = "",
string name = "" )

create_component_by_name
function ovm_component create_component_by_name ( string requested_type_name,
string parent_inst_path = "",
string name,
ovm_component parent )

Creates and returns a component or object of the requested type, which may be specified by type or by name. A requested
component must be derived from theovm_component base class, and a requested object must be derived from the ovm_objectbase
class.
When requesting by type, the requested_type is a handle to the types proxy object. Preregistration is not required.
When requesting by name, the request_type_name is a string representing the requested type, which must have been registered with
the factory with that name prior to the request. If the factory does not recognize the requested_type_name, an error is produced and a
null handle returned.
If the optional parent_inst_path is provided, then the concatenation, {parent_inst_path, .,~name~}, forms an instance path
(context) that is used to search for an instance override. The parent_inst_path is typically obtained by calling
theovm_component::get_full_name on the parent.
If no instance override is found, the factory then searches for a type override.
Once the final override is found, an instance of that component or object is returned in place of the requested type. New components
will have the given name and parent. New objects will have the given name, if provided.
Override searches are recursively applied, with instance overrides taking precedence over type overrides. If foo overrides bar,
and xyz overrides foo, then a request for bar will produce xyz. Recursive loops will result in an error, in which case the type returned
will be that which formed the loop. Using the previous example, if bar overrides xyz, then baris returned after the error is issued.
DEBUG
debug_create_by_type
function void debug_create_by_type ( ovm_object_wrapper requested_type,
string parent_inst_path = "",
string name = "" )

debug_create_by_name
function void debug_create_by_name ( string requested_type_name,
string parent_inst_path = "",
string name = "" )

These methods perform the same search algorithm as the create_* methods, but they do not create new objects. Instead, they provide
detailed information about what type of object it would return, listing each override that was applied to arrive at the
result. Interpretation of the arguments are exactly as with the create_* methods.
find_override_by_type
function ovm_object_wrapper find_override_by_type (
ovm_object_wrapper requested_type,
string full_inst_path
)

find_override_by_name
function ovm_object_wrapper find_override_by_name ( string requested_type_name,
string full_inst_path )

These methods return the proxy to the object that would be created given the arguments. The full_inst_path is typically derived from
the parents instance path and the leaf name of the object to be created, i.e. { parent.get_full_name(), ., name }.
print
function void print ( int all_types = 1 )

Prints the state of the ovm_factory, including registered types, instance overrides, and type overrides.
When all_types is 0, only type and instance overrides are displayed. When all_types is 1 (default), all registered user-defined types
are printed as well, provided they have names associated with them. When all_types is 2, the OVM types (prefixed with ovm_) are
included in the list of registered types.
USAGE
Using the factory involves three basic operations
1 Registering objects and components types with the factory
2 Designing components to use the factory to create objects or components
3 Configuring the factory with type and instance overrides, both within and outside components
Well briefly cover each of these steps here. More reference information can be found atUtility
Macros, ovm_component_registry #(T,Tname), ovm_object_registry #(T,Tname),ovm_component.
1 -- Registering objects and component types with the factory
When defining ovm_object and ovm_component-based classes, simply invoke the appropriate
macro. Use of macros are required to ensure portability across different vendors simulators.
Objects that are not parameterized are declared as
class packet extends ovm_object;
`ovm_object_utils(packet)
endclass

class packetD extends packet;
`ovm_object_utils(packetD)
endclass
Objects that are parameterized are declared as
class packet #(type T=int, int WIDTH=32) extends ovm_object;
`ovm_object_param_utils(packet #(T,WIDTH))
endclass
Components that are not parameterized are declared as
class comp extends ovm_component;
`ovm_component_utils(comp)
endclass
Components that are parameterized are declared as
class comp #(type T=int, int WIDTH=32) extends ovm_component;
`ovm_component_param_utils(comp #(T,WIDTH))
endclass
The `ovm_*_utils macros for simple, non-parameterized classes will register the type with the factory
and define the get_type, get_type_name, and create virtual methods inherited from ovm_object. It will
also define a static type_name variable in the class, which will allow you to determine the type without
having to allocate an instance.
The `ovm_*_param_utils macros for parameterized classes differ from `ovm_*_utils classes in the
following ways:
The get_type_name method and static type_name variable are not defined. You will need to
implement these manually.
A type name is not associated with the type when registeriing with the factory, so the factorys
*_by_name operations will not work with parameterized classes.
The factorys print, debug_create_by_type, and debug_create_by_name methods, which depend on
type names to convey information, will list parameterized types as <unknown>.
It is worth noting that environments that exclusively use the type-based factory methods (*_by_type) do
not require type registration. The factorys type-based methods will register the types involved on the
fly, when first used. However, registering with the `ovm_*_utils macros enables name-based factory
usage and implements some useful utility functions.
2 -- Designing components that defer creation to the factory
Having registered your objects and components with the factory, you can now make requests for new
objects and components via the factory. Using the factory instead of allocating them directly (via new)
allows different objects to be substituted for the original without modifying the requesting class. The
following code defines a driver class that is parameterized.
class driverB #(type T=ovm_object) extends ovm_driver;

// parameterized classes must use the _param_utils version
`ovm_component_param_utils(driverB #(T))

// our packet type; this can be overridden via the factory
T pkt;

// standard component constructor
function new(string name, ovm_component parent=null);
super.new(name,parent);
endfunction

// get_type_name not implemented by macro for parameterized classes
const static string type_name = {"driverB #(",T::type_name,")"};
virtual function string get_type_name();
return type_name;
endfunction

// using the factory allows pkt overrides from outside the class
virtual function void build();
pkt = packet::type_id::create("pkt",this);
endfunction

// print the packet so we can confirm its type when printing
virtual function void do_print(ovm_printer printer);
printer.print_object("pkt",pkt);
endfunction

endclass

For purposes of illustrating type and instance overrides, we define two subtypes of thedriverB class. The
subtypes are also parameterized, so we must again provide an implementation
for ovm_object::get_type_name, which we recommend writing in terms of a static string constant.
class driverD1 #(type T=ovm_object) extends driverB #(T);

`ovm_component_param_utils(driverD1 #(T))

function new(string name, ovm_component parent=null);
super.new(name,parent);
endfunction

const static string type_name = {"driverD1 #(",T::type_name,")"};
virtual function string get_type_name();
...return type_name;
endfunction

endclass

class driverD2 #(type T=ovm_object) extends driverB #(T);

`ovm_component_param_utils(driverD2 #(T))

function new(string name, ovm_component parent=null);
super.new(name,parent);
endfunction

const static string type_name = {"driverD2 #(",T::type_name,")"};
virtual function string get_type_name();
return type_name;
endfunction

endclass

// typedef some specializations for convenience
typedef driverB #(packet) B_driver; // the base driver
typedef driverD1 #(packet) D1_driver; // a derived driver
typedef driverD2 #(packet) D2_driver; // another derived driver
Next, well define a agent component, which requires a utils macro for non-parameterized types. Before
creating the drivers using the factory, we override driver0s packet type to be packetD.
class agent extends ovm_agent;

`ovm_component_utils(agent)
...
B_driver driver0;
B_driver driver1;

function new(string name, ovm_component parent=null);
super.new(name,parent);
endfunction

virtual function void build();

// override the packet type for driver0 and below
packet::type_id::set_inst_override(packetD::get_type(),"driver0.*");

// create using the factory; actual driver types may be different
driver0 = B_driver::type_id::create("driver0",this);
driver1 = B_driver::type_id::create("driver1",this);

endfunction

endclass
Finally we define an environment class, also not parameterized. Its build method shows three methods
for setting an instance override on a grandchild component with relative path name, agent1.driver1, all
equivalent.
class env extends ovm_env;

`ovm_component_utils(env)

agent agent0;
agent agent1;

function new(string name, ovm_component parent=null);
super.new(name,parent);
endfunction

virtual function void build();

// three methods to set an instance override for agent1.driver1
// - via component convenience method...
set_inst_override_by_type("agent1.driver1",
B_driver::get_type(),
D2_driver::get_type());

// - via the component's proxy (same approach as create)...
B_driver::type_id::set_inst_override(D2_driver::get_type(),
"agent1.driver1",this);

// - via a direct call to a factory method...
factory.set_inst_override_by_type(B_driver::get_type(),
D2_driver::get_type(),
{get_full_name(),".agent1.driver1"});

// create agents using the factory; actual agent types may be different
agent0 = agent::type_id::create("agent0",this);
agent1 = agent::type_id::create("agent1",this);

endfunction

// at end_of_elaboration, print topology and factory state to verify
virtual function void end_of_elaboration();
ovm_top.print_topology();
endfunction

virtual task run();
#100 global_stop_request();
endfunction

endclass
3 -- Configuring the factory with type and instance overrides
In the previous step, we demonstrated setting instance overrides and creating components using the
factory within component classes. Here, we will demonstrate setting overrides from outside components,
as when initializing the environment prior to running the test.
module top;

env env0;

initial begin

// Being registered first, the following overrides take precedence
// over any overrides made within env0's construction & build.

// Replace all base drivers with derived drivers...
B_driver::type_id::set_type_override(D_driver::get_type());

// ...except for agent0.driver0, whose type remains a base driver.
// (Both methods below have the equivalent result.)

// - via the component's proxy (preferred)
B_driver::type_id::set_inst_override(B_driver::get_type(),
"env0.agent0.driver0");

// - via a direct call to a factory method
factory.set_inst_override_by_type(B_driver::get_type(),
B_driver::get_type(),
{get_full_name(),"env0.agent0.driver0"});

// now, create the environment; our factory configuration will
// govern what topology gets created
env0 = new("env0");

// run the test (will execute build phase)
run_test();

end

endmodule
When the above example is run, the resulting topology (displayed via a call to <ovm_top.print_topology>
in envs ovm_component::end_of_elaboration method) is similar to the following:
# OVM_INFO @ 0 [RNTST] Running test ...
# OVM_INFO @ 0 [OVMTOP] OVM testbench topology:
# ----------------------------------------------------------------------
# Name Type Size Value
# ----------------------------------------------------------------------
# env0 env - env0@2
# agent0 agent - agent0@4
# driver0 driverB #(packet) - driver0@8
# pkt packet - pkt@21
# driver1 driverD #(packet) - driver1@14
# pkt packet - pkt@23
# agent1 agent - agent1@6
# driver0 driverD #(packet) - driver0@24
# pkt packet - pkt@37
# driver1 driverD2 #(packet) - driver1@30
# pkt packet - pkt@39
# ---------------------------------------------

(Q 45) Explain the mechanism involved in TLM ports.
TLM Interfaces, Ports, and Exports
The OVM TLM library defines several abstract, transaction-level interfaces and the ports and exports that
facilitate their use. Each TLM interface consists of one or more methods used to transport data, typically
whole transactions (objects) at a time. Component designs that use TLM ports and exports to
communicate are inherently more reusable, interoperable, and modular.
Interface Overview
The TLM standard specifies the required behavior (semantic) of each interface method. Classes
(components) that implement a TLM interface must meet the specified semantic.
Each TLM interface is either blocking, non-blocking, or a combination of these two.
blocking A blocking interface conveys transactions in blocking fashion; its methods do not return until the transaction
has been successfully sent or retrieved. Because delivery may consume time to complete, the methods in
such an interface are declared as tasks.
non-blocking A non-blocking interface attempts to convey a transaction without consuming simulation time. Its methods
are declared as functions. Because delivery may fail (e.g. the target component is busy and can not accept
the request), the methods may return with failed status.
combination A combination interface contains both the blocking and non-blocking variants. In SystemC, combination
interfaces are defined through multiple inheritance. Because SystemVerilog does not support multiple
inheritance, the OVM emulates hierarchical interfaces via a common base class and interface mask.
Like their SystemC counterparts, the OVMs TLM port and export implementations allow connections
between ports whose interfaces are not an exact match. For example, anovm_blocking_get_port can be
connected to any port, export or imp port that provides at the least an implementation of the
blocking_get interface, which includes the ovm_get_*ports and exports, ovm_blocking_get_peek_* ports
and exports, and ovm_get_peek_*ports and exports.
The sections below provide and overview of the unidirectional and bidirectional TLM interfaces, ports, and
exports.

Summary
TLM Interfaces, Ports, and Exports
The OVM TLM library defines several abstract, transaction-level interfaces and the ports and exports
that facilitate their use.
UNIDIRECTIONAL
INTERFACES & PORTS
The unidirectional TLM interfaces consist of blocking, non-blocking, and
combined blocking and non-blocking variants of
the put, get and peek interfaces, plus a non-blockinganalysis interface.
Put The put interfaces are used to send, or put, transactions to other
components.
Get and Peek The get interfaces are used to retrieve transactions from other
components.
Analysis The analysis interface is used to perform non-blocking broadcasts of
transactions to connected components.
Ports, Exports,
and Imps
The OVM provides unidirectional ports, exports, and implementation
ports for connecting your components via the TLM interfaces.
BIDIRECTIONAL
INTERFACES & PORTS
The bidirectional interfaces consist of blocking, non-blocking, and
combined blocking and non-blocking variants of thetransport, master,
and slave interfaces.
Transport The transport interface sends a request transaction and returns a
response transaction in a single task call, thereby enforcing an in-order
execution semantic.
Master and The primitive, unidirectional put, get, and peek interfaces are combined
Slave to form bidirectional master and slave interfaces.
Ports, Exports,
and Imps
The OVM provides bidirectional ports, exports, and implementation
ports for connecting your components via the TLM interfaces.
USAGE We provide an example to illustrate basic TLM connectivity using the
blocking put inteface.
UNIDIRECTIONAL INTERFACES & PORTS
The unidirectional TLM interfaces consist of blocking, non-blocking, and combined blocking and non-
blocking variants of the put, get and peek interfaces, plus a non-blockinganalysis interface.

Put
The put interfaces are used to send, or put, transactions to other components. Successful completion of
a put guarantees its delivery, not execution.

Get and Peek
The get interfaces are used to retrieve transactions from other components. The peekinterfaces are used
for the same purpose, except the retrieved transaction is not consumed; successive calls to peek will
return the same object. Combined get_peekinterfaces are also defined.

Analysis
The analysis interface is used to perform non-blocking broadcasts of transactions to connected
components. It is typically used by such components as monitors to publish transactions observed on a
bus to its subscribers, which are typically scoreboards and response/coverage collectors.

Ports, Exports, and Imps
The OVM provides unidirectional ports, exports, and implementation ports for connecting your
components via the TLM interfaces.
Ports instantiated in components that require, or use, the associate interface to initiate transaction requests.
Exports instantiated by components that forward an implementation of the methods defined in the associated
interface. The implementation is typically provided by an imp port in a child component.
Imps instantiated by components that provide or implement an implementation of the methods defined in the
associated interface.

A summary of port, export, and imp declarations are
class ovm_*_export #(type T=int)
extends ovm_port_base #(tlm_if_base #(T,T));

class ovm_*_port #(type T=int)
extends ovm_port_base #(tlm_if_base #(T,T));

class ovm_*_imp #(type T=int)
extends ovm_port_base #(tlm_if_base #(T,T));
where the asterisk can be any of
blocking_put
nonblocking_put
put

blocking_get
nonblocking_get
get

blocking_peek
nonblocking_peek
peek

blocking_get_peek
nonblocking_get_peek
get_peek

analysis
BIDIRECTIONAL INTERFACES & PORTS
The bidirectional interfaces consist of blocking, non-blocking, and combined blocking and non-blocking
variants of the transport, master, and slave interfaces.
Bidirectional interfaces involve both a transaction request and response.
Transport
The transport interface sends a request transaction and returns a response transaction in a single task
call, thereby enforcing an in-order execution semantic. The request and response transactions can be
different types.

Master and Slave
The primitive, unidirectional put, get, and peek interfaces are combined to form bidirectional master and
slave interfaces. The master puts requests and gets or peeks responses. The slave gets or peeks
requests and puts responses. Because the put and the get come from different function interface
methods, the requests and responses are not coupled as they are with the transport interface.

Ports, Exports, and Imps
The OVM provides bidirectional ports, exports, and implementation ports for connecting your components
via the TLM interfaces.
Ports instantiated in components that require, or use, the associate interface to initiate transaction requests.
Exports instantiated by components that forward an implementation of the methods defined in the associated
interface. The implementation is typically provided by an imp port in a child component.
Imps instantiated by components that provide or implement an implementation of the methods defined in the
associated interface.

A summary of port, export, and imp declarations are
class ovm_*_port #(type REQ=int, RSP=int)
extends ovm_port_base #(tlm_if_base #(REQ, RSP));

class ovm_*_export #(type REQ=int, RSP=int)
extends ovm_port_base #(tlm_if_base #(REQ, RSP));

class ovm_*_imp #(type REQ=int, RSP=int)
extends ovm_port_base #(tlm_if_base #(REQ, RSP));
where the asterisk can be any of
transport
blocking_transport
nonblocking_transport

blocking_master
nonblocking_master
master

blocking_slave
nonblocking_slave
slave
USAGE
We provide an example to illustrate basic TLM connectivity using the blocking put inteface.

port-to-port leaf1s out port is connected to its parents (comp1)out port
port-to-export comp1s out port is connected to comp2s in export
export-to-export comp2s in export is connected to its childs (subcomp2) in export
export-to-imp subcomp2s in export is connected leaf2s in imp port.
imp-to-implementation leaf2s in imp port is connected to its implementation, leaf2
Hierarchical port connections are resolved and optimized just before
theovm_component::end_of_elaboration phase. After optimization, calling any ports interface method
(e.g. leaf1.out.put(trans)) incurs a single hop to get to the implementation (e.g. leaf2s put task), no
matter how far up and down the hierarchy the implementation resides.

`include "ovm_pkg.sv"
import ovm_pkg::*;

class trans extends ovm_transaction;
rand int addr;
rand int data;
rand bit write;
endclass

class leaf1 extends ovm_component;

`ovm_component_utils(leaf1)

ovm_blocking_put_port #(trans) out;

function new(string name, ovm_component parent=null);
super.new(name,parent);
out = new("out",this);
endfunction

virtual task run();
trans t;
t = new;
t.randomize();
out.put(t);
endtask

endclass


class comp1 extends ovm_component;

`ovm_component_utils(comp1)

ovm_blocking_put_port #(trans) out;

leaf1 leaf;

function new(string name, ovm_component parent=null);
super.new(name,parent);
endfunction

virtual function void build();
out = new("out",this);
leaf = new("leaf1",this);
endfunction

// connect port to port
virtual function void connect();
leaf.out.connect(out);
endfunction

endclass


class leaf2 extends ovm_component;

`ovm_component_utils(leaf2)

ovm_blocking_put_imp #(trans,leaf2) in;

function new(string name, ovm_component parent=null);
super.new(name,parent);
// connect imp to implementation (this)
in = new("in",this);
endfunction

virtual task put(trans t);
$display("Got trans: addr=%0d, data=%0d, write=%0d",
t.addr, t.data, t.write);
endtask

endclass


class subcomp2 extends ovm_component;

`ovm_component_utils(subcomp2)

ovm_blocking_put_export #(trans) in;

leaf2 leaf;

function new(string name, ovm_component parent=null);
super.new(name,parent);
endfunction

virtual function void build();
in = new("in",this);
leaf = new("leaf2",this);
endfunction

// connect export to imp
virtual function void connect();
in.connect(leaf.in);
endfunction

endclass


class comp2 extends ovm_component;

`ovm_component_utils(comp2)

ovm_blocking_put_export #(trans) in;

subcomp2 subcomp;

function new(string name, ovm_component parent=null);
super.new(name,parent);
endfunction

virtual function void build();
in = new("in",this);
subcomp = new("subcomp2",this);
endfunction

// connect export to export
virtual function void connect();
in.connect(subcomp.in);
endfunction

endclass


class env extends ovm_component;

`ovm_component_utils(comp1)

comp1 comp1_i;
comp2 comp2_i;

function new(string name, ovm_component parent=null);
super.new(name,parent);
endfunction

virtual function void build();
comp1_i = new("comp1",this);
comp2_i = new("comp2",this);
endfunction

// connect port to export
virtual function void connect();
comp1_i.out.connect(comp2_i.in);
endfunction

endclass


module top;
env e = new("env");
initial run_test();
initial #10 ovm_top.stop_request();
endmodule

(Q i46) Why TLM fifo is used ?
Tlm Fifo
Tlm_fifo provides storage of transactions between two independently running processes just like mailbox.
Transactions are put into the FIFO via the put_export and fetched from the get_export.
In this example, we will use a tlm_fifo to connect producer and consumer.
The producer component generates the transaction and using its put_port pot() method, sends transaction out.
The consumer component, to get the transaction from outside, uses get() method of get_port. These two ports
are connected to tlm_fifo in the env class. In this example, producer and consumer are initiators as both
components are calling the methods.




(S)Producer source code:

class producer extends uvm_component;
uvm_blocking_put_port#(int) put_port;

function new(string name, uvm_component p = null);
super.new(name,p);
put_port = new("put_port", this);

endfunction

task run;
int randval;
for(int i = 0; i < 10; i++)
begin
#10;
randval = $urandom_range(4,10);
`uvm_info("producer",
$sformatf("sending %d",randval), UVM_MEDIUM)
put_port.put(randval);
end
endtask

endclass : producer

(S)Consumer source code:
class consumer extends uvm_component;
uvm_blocking_get_port#(int) get_port;

function new(string name, uvm_component p = null);
super.new(name,p);
get_port = new("get_port", this);
endfunction

task run;
int val;
forever
begin
get_port.get(val);
`uvm_info("consumer",
$sformatf("receiving %d", val), UVM_MEDIUM)
end
endtask

endclass : consumer

(S)Env source code:
class env extends uvm_env;
producer p;
consumer c;
tlm_fifo #(int) f;

function new(string name = "env");
super.new(name);
p = new("producer", this);
c = new("consumer", this);
f = new("fifo", this);
endfunction

function void connect();
p.put_port.connect(f.put_export);
c.get_port.connect(f.get_export);
endfunction

task run();
#1000 global_stop_request();
endtask

endclass



(Q i47)How to add a user defined phase ?
ovm_phase
The ovm_phase class is used for defining phases for ovm_component and its subclasses. For a list of
predefined phases see ovm_component::Phasing Interface
Summary
ovm_phase
The ovm_phase class is used for defining phases for ovm_component and its subclasses.
CLASS DECLARATION
virtual class ovm_phase

METHODS
new Creates a phase object.
get_name Returns the name of the phase object as supplied in the constructor.
is_task Returns 1 if the phase is time consuming and 0 if not.
is_top_down Returns 1 if the phase executes top-down (executes the parents phase
callback before executing the childrens callback) and 0 otherwise.
get_type_name Derived classes should override this method to return the phase type
name.
wait_start Waits until the phase has beed started.
wait_done Waits until the phase has been completed.
is_in_progress Returns 1 if the phase is currently in progress (active), 0 otherwise.
is_done Returns 1 if the phase has completed, 0 otherwise.
reset Resets phase state such that is_done and is_in_progress both return 0.
call_task Calls the task-based phase of the component given by parent, which
must be derived from ovm_component.
call_func Calls the function-based phase of the component given by parent.

METHODS
new
function new ( string name,
bit is_top_down,
bit is_task )

Creates a phase object.
The name is the name of the phase. When is_top_down is set, the parent is phased before its children.
is_task indicates whether the phase callback is a task (1) or function (0). Only tasks may consume
simulation time and execute blocking statements.
get_name
function string get_name ()
Returns the name of the phase object as supplied in the constructor.
is_task
function bit is_task ()
Returns 1 if the phase is time consuming and 0 if not.
is_top_down
function bit is_top_down ()
Returns 1 if the phase executes top-down (executes the parents phase callback before executing the
childrens callback) and 0 otherwise.
get_type_name
virtual function string get_type_name()
Derived classes should override this method to return the phase type name.
wait_start
task wait_start ()
Waits until the phase has beed started.
wait_done
task wait_done ()
Waits until the phase has been completed.
is_in_progress
function bit is_in_progress ()
Returns 1 if the phase is currently in progress (active), 0 otherwise.
is_done
function bit is_done ()
Returns 1 if the phase has completed, 0 otherwise.
reset
function void reset ()
Resets phase state such that is_done and is_in_progress both return 0.
call_task
virtual task call_task ( ovm_component parent )

Calls the task-based phase of the component given by parent, which must be derived from
ovm_component. A task-based phase is defined by subtyping ovm_phase and overriding this
method. The override must $cast the base parent handle to the actual component type that defines the
phase callback, and then call the phase callback.
call_func
virtual function void call_func ( ovm_component parent )

Calls the function-based phase of the component given by parent. A function-based phase is defined by
subtyping ovm_phase and overriding this method. The override must $cast the base parent handle to
the actual component type that defines the phase callback, and then call that phase callback.
Usage
Phases are a synchronizing mechanism for the environment. They are represented by callback
methods. A set of predefined phases and corresponding callbacks are provided in ovm_component. Any
class deriving from ovm_component may implement any or all of these callbacks, which are executed in a
particular order. Depending on the properties of any given phase, the corresponding callback is either a
function or task, and it is executed in top-down or bottom-up order.
The OVM provides the following predefined phases for all ovm_components.
build Depending on configuration and factory settings, create and configure additional
component hierarchies.
connect Connect ports, exports, and implementations (imps).
end_of_elaboration Perform final configuration, topology, connection, and other integrity checks.
start_of_simulation Do pre-run activities such as printing banners, pre-loading memories, etc.
run Most verification is done in this time-consuming phase. May fork other processes. Phase
ends when global_stop_request is called explicitly.
extract Collect information from the run in preparation for checking.
check Check simulation results against expected outcome.
report Report simulation results.
A phase is defined by an instance of an ovm_phase subtype. If a phase is to be shared among several
component types, the instance must be accessible from a common scope, such as a package.
To have a user-defined phase get called back during simulation, the phase object must be registered with
the top-level OVM phase controller, ovm_top.
Inheriting from the ovm_phase Class
When creating a user-defined phase, you must do the following.
1. Define a new phase class, which must extend ovm_phase. To enable use of the phase by any
component, we recommend this class be parameterized. The easiest way to define a new phase is to
invoke a predefined macro. For example:
`ovm_phase_func_topdown_decl( preload )
This convenient phase declaration macro is described below.
2. Create a single instance of the phase in a convenient placein a package, or in the same scope as the
component classes that will use the phase.
typedef class my_memory;
preload_phase #(my_memory) preload_ph = new;
3. Register the phase object with ovm_top.
class my_memory extends ovm_component;
function new(string name, ovm_component parent);
super.new(name,parent);
ovm_top.insert_phase(preload_ph, start_of_simulation_ph);
endfunction
virtual function void preload(); // our new phase
...
endfunction
endclass
Phase Macros (Optional)
The following macros simplify the process of creating a user-defined phase. They create a phase type
that is parameterized to the component class that uses the phase.
Summary
Usage Phases are a synchronizing mechanism for the
environment.
MACROS
`ovm_phase_func_decl `ovm_phase_func_decl (PHASE_NAME, TOP_DOWN)
`ovm_phase_task_decl
`ovm_phase_func_topdown_decl
`ovm_phase_func_bottomup_decl
`ovm_phase_task_topdown_decl
`ovm_phase_task_bottomup_decl These alternative macros have a single phase name
argument.
MACROS
`ovm_phase_func_decl
`ovm_phase_func_decl (PHASE_NAME, TOP_DOWN)
The PHASE_NAME argument is used to define the name of the phase, the name of the component
method that is called back during phase execution, and the prefix of the type-name of the phase class
that gets generated.
The above macro creates the following class definition.
class PHASE_NAME``_phase #(type PARENT=int) extends ovm_phase;
PARENT m_parent;
function new();
super.new(`"NAME`",TOP_DOWN,1);
endfunction
virtual function void call_func();
m_parent.NAME(); // call the components phase callback
endtask
virtual task execute(ovm_component parent);
assert($cast(m_parent,parent));
call_func();
endtask
endclass
`ovm_phase_task_decl
`ovm_phase_task_decl (PHASE_NAME, TOP_DOWN)
The above macro creates the following class definition.
class PHASE_NAME``_phase #(type PARENT=int) extends ovm_phase;
PARENT m_parent;
function new();
super.new(`"NAME`",TOP_DOWN,1);
endfunction
virtual task call_task();
m_parent.NAME(); // call the components phase callback
endtask
virtual task execute(ovm_component parent);
assert($cast(m_parent,parent));
call_task();
endtask
endclass
`ovm_phase_func_topdown_decl
`ovm_phase_func_bottomup_decl
`ovm_phase_task_topdown_decl
`ovm_phase_task_bottomup_decl
These alternative macros have a single phase name argument. The top-down or bottom-up selection is
specified in the macro name, which makes them more self-documenting than those with a 0 or 1 2nd
argument.
`define ovm_phase_func_topdown_decl `ovm_phase_func_decl (PHASE_NAME,1)
`define ovm_phase_func_bottomup_decl `ovm_phase_func_decl (PHASE_NAME,0)
`define ovm_phase_task_topdown_decl `ovm_phase_task_decl (PHASE_NAME,1)
`define ovm_phase_task_bottomup_decl `ovm_phase_task_decl (PHASE_NAME,0)


(Q i48) What are the ways to get the configuration information inside component ?
OVM CONFIGURATION




Configuration is a mechanism in OVM that higher level components in a hierarchy can configure the lower level
components variables. Using set_config_* methods, user can configure integer, string and objects of lower level
components. Without this mechanism, user should access the lower level component using hierarchy paths,
which restricts reusability. This mechanism can be used only with components. Sequences and transactions
cannot be configured using this mechanism. When set_config_* method is called, the data is stored w.r.t strings
in a table. There is also a global configuration table.

Higher level component can set the configuration data in level component table. It is the responsibility of the
lower level component to get the data from the component table and update the appropriate table.
Set_config_* Methods:



Following are the method to configure integer , string and object of ovm_object based class respectively.


function void set_config_int (string inst_name,
string field_name,
ovm_bitstream_t value)

function void set_config_string (string inst_name,
string field_name,
string value)

function void set_config_object (string inst_name,
string field_name,
ovm_object value, bit clone = 1)


(S)Arguments description:


string inst_name: Hierarchical string path.
string field_name: Name of the field in the table.
bitstream_t value: In set_config_int, a integral value that can be anything from 1 bit to 4096 bits.
bit clone : If this bit is set then object is cloned.

inst_name and field_name are strings of hierarchal path. They can include wile card "*" and "?" characters. These
methods must be called in build phase of the component.





"*" matches zero or more characters
"?" matches exactly one character




(S)Some examples:


"*" -All the lower level components.

"*abc" -All the lower level components which ends with "abc".
Example: "xabc","xyabc","xyzabc" ....

"abc*" -All the lower level components which starts with "abc".
Example: "abcx","abcxy","abcxyz" ....

"ab?" -All the lower level components which start with "ab" , then followed by one more character.
Example: "abc","abb","abx" ....

"?bc" -All the lower level components which start with any one character ,then followed by "c".
Example: "abc","xbc","bbc" ....

"a?c" -All the lower level components which start with "a" , then followed by one more character and then
followed by "c".
Example: "abc","aac","axc" ~@..






There are two ways to get the configuration data:
1)Automatic : Using Field macros
2)Manual : using gte_config_* methods.



Automatic Configuration:



To use the atomic configuration, all the configurable fields should be defined using ovm component field macros
and ovm component utilities macros.


(S)Ovm component utility macros:
For non parameterized classes
`ovm_component_utils_begin(TYPE)
`ovm_field_* macro invocations here
`ovm_component_utils_end
For parameterized classes.
`ovm_component_param_utils_begin(TYPE)
`ovm_field_* macro invocations here
`ovm_component_utils_end



For OVM Field macros, Refer to link
OVM_TRANSACTION

Example:
Following example is from link
OVM_TESTBENCH

2 Configurable fields, a integer and a string are defined in env, agent, monitor and driver classes. Topology of
the environment using these classes is




(S)Driver class Source Code:


Similar to driver class, all other components env, agent and monitor are define.


class driver extends ovm_driver;

integer int_cfg;
string str_cfg;

`ovm_component_utils_begin(driver)
`ovm_field_int(int_cfg, OVM_DEFAULT)
`ovm_field_string(str_cfg, OVM_DEFAULT)
`ovm_component_utils_end

function new(string name, ovm_component parent);
super.new(name, parent);
endfunction

function void build();
super.build();
endfunction

endclass

(S)Testcase:


Using set_config_int() and set_config_string() configure variables at various hierarchal locations.


//t_env.ag1.drv.int_cfg
//t_env.ag1.mon.int_cfg
set_config_int("*.ag1.*","int_cfg",32);

//t_env.ag2.drv
set_config_int("t_env.ag2.drv","int_cfg",32);

//t_env.ag2.mon
set_config_int("t_env.ag2.mon","int_cfg",32);

//t_env.ag1.mon.str_cfg
//t_env.ag2.mon.str_cfg
//t_env.ag1.drv.str_cfg
//t_env.ag2.drv.str_cfg
set_config_string("*.ag?.*","str_cfg","pars");

//t_env.str_cfg
set_config_string("t_env","str_cfg","abcd");

(S)Download the source code


ovm_configuration_1.tar
Browse the code in ovm_configuration_1.tar


(S)Command to run the simulation


your_tool_simulation_command +path_to_ovm_pkg -f filelist +OVM_TESTNAME=test1





From the above log report of th example, we can see the variables int_cfg and str_cfg of all the components and
they are as per the configuration setting from the testcase.



Manual Configurations:



Using get_config_* methods, user can get the required data if the data is available in the table.
Following are the method to get configure data of type integer , string and object of ovm_object based class
respectively.


function bit get_config_int (string field_name,
inout ovm_bitstream_t value)

function bit get_config_string (string field_name,
inout string value)

function bit get_config_object (string field_name,
inout ovm_object value,
input bit clone = 1)



If a entry is found in the table with "field_name" then data will be updated to "value" argument . If entry is not
found, then the function returns "0". So when these methods are called, check the return value.


Example:
(S)Driver class code:
class driver extends ovm_driver;

integer int_cfg;
string str_cfg;

`ovm_component_utils(driver)

function new(string name, ovm_component parent);
super.new(name, parent);
endfunction

function void build();
super.build();
void'(get_config_int("int_cfg",int_cfg));
void'(get_config_string("str_cfg",str_cfg));
ovm_report_info(get_full_name(),
$psprintf("int_cfg %0d : str_cfg %0s ",int_cfg,str_cfg),OVM_LOW);
endfunction

endclass
Configuration Setting Members:


(S)print_config_settings
function void print_config_settings
( string field = "",
ovm_component comp = null,
bit recurse = 0 )


This method prints all configuration information for this component.
If "field" is specified and non-empty, then only configuration settings matching that field, if any, are printed.
The field may not contain wildcards. If "recurse" is set, then information for all children components are printed
recursively.



(S)print_config_matches
static bit print_config_matches = 0


Setting this static variable causes get_config_* to print info about matching configuration settings as they are
being applied. These two members will be helpful to know while debugging.

(Q i49) Is it possible to use get_config_obj inside a sequence class?


(Q i50)Whato eisi theodifference qbetweenre create iandoq jnewre method i?

(Q i51)Whato eisi virtualosequencer q?re Explain ibyoq jwritingre example.

(Q i52)Howo eai sequenceois qstartedre ?

(Q i53)Explaino eendi ofotest qmechanism.re

(Q i54)When/howo ethei stop()omethod qisre called i? www.testbench.in


(Q i55)Whato eisi port/import/exporto?

(Q i56)Whicho ephasei isotop qdown,re and iwhichoq jphasere is ibottom oup?

(Q i57)Ino ewhichi phaseomethod, qsuperre method iisoq jrequiredre to icall. oqWhat ifz theu ysupere oiszx not
called ?

(Q i58)Explaino ethei differentophases qandre what iisoq jtheirre purpose......w.....w......w......t.....e.....s.....t......b.....e....
.n.....c.....h......i.....n


(Q i59)Howo etoi useofactory qoverridere a isequenceoq j?re www.testbench.in


(Q i60)Explaino ehowi scoreboardois qimplemented.re

(Q i61)Whato eisi theouse qofre subscriber i?

(Q i62)Explaino eabouti run_test().

(Q i63)Howo einterfacei isopassed qtore component.

(Q i64)Whato eisi theodifferent qb/wre active iagentoq jandre passive iagent o?www.testbench.in


(Q i65)Explaino ehowi aointerrupt qsequencere is iimplemented.

(Q i66)Explaino ehowi layeredosequencers qarere implemented.

(Q i67)Howo etoi changeothe qverbosityre level iofoq jlogre messages ifromocommandqline ?
.....w.....w......w......t.....e.....s.....t......b.....e.....n.....c.....h......i.....n

(Q i68)Howo etoi setoverbosity qlevelre to ioneoq jparticularre component i?

(Q i69)Howo etoi fillothe qgapre b/w idifferentoq jobjections? www.testbench.in


(Q i70)Whato eisi theouse qofre uvm_event i?

(Q i71)Howo etoi connectomultiple qsequencersre to ioneoq jdriverre ?

(Q i72)Whato eisi returnedoby qget_type_name()?

(Q i73)Howo etoi useoset_config_* qforre setting ivariablesoq jofre sequence i?

(Q i74)Foro edebuggingi purpose,ohow qtore print imessagesoq jthatre indicates itheocomponentsqphase
? www.testbench.in


(Q i75)Whato eisi theodisadvantage qifre sequence iisoq jregisterdre to isequencerousingqutility
macrosz ?u ye oIfzx sequence is not registered with sequencer, then how to invoke the sequence execution ?

(Q i76)Whato eisi theouse qofre uvm_create_random_seed i?

(Q i77)Whato eisi theodifference qb/wre starting iaoq jsequencere usingidefault_sequence oandqsequence.start(
) method.z.....w.....w......w......t.....e.....s.....t......b.....e.....n.....c.....h......i.....n


(Q i78)Io edon~Rti wantoto qregisterre a isequenceoq jtore sequencer. iWhat oisqthe
alternatez macrou ytoe ouvm_sequence_utils()zx macro ?

(Q i79)Explaino ehowi UVMocallbacks qworkre ? www.testbench.in


(Q i80)o eWhati isothe qdifferencere b/w im_sequenceroq jandre p_sequencer i?

You might also like