04.UVM_Factory Method - mbits-mirafra/UVMCourse GitHub Wiki
uvm_factory
As the name says, uvm_factory is used to create components and objects. UVM Factory is also known as Factory registration. With the help of lightweight proxies, Object and component types are registered with the factory to the actual objects and components being created.
Steps to follow to make use of factory
- Factory registration
- Default constructor new()
- Component and object creation
- Factory Overriding (if needed)
1. Factory registration
Using a pre-defined factory macro both uvm_component and uvm_object must be registered with the factory.
Factory registration for uvm_component
class our_test extends uvm_test;
// factory registration for test
`uvm_component_utils(our_test)
...
...
endclass
Factory registration for uvm_object
class reg_seq extends uvm_sequence #(seq_item);
// factory registration for sequence
`uvm_object_utils(reg_seq)
...
...
endclass
2. Default constructor new()
The constructors for uvm_object and uvm_components are virtual methods that are they have a fixed template that needs to be followed.
Constructor for uvm_component
Two arguments are provided for the default constructor: name and parent.
- The name denotes an instance name for an object.
- The parent denotes the handle to its parent. In the constructor, the parent argument is null and the actual parent can be provided while creating an object.
- All derived classes must call super.new() methods.
Note Any component whose parent is set to null becomes a child of uvm_top.
class our_test extends uvm_component_name;
`uvm_component_utils(our_test)
// default constructor for test
function new(string name = "our_test", uvm_component_name parent)
super.new(name, parent);
endfunction
...
...
endclass
Constructor for uvm_object
In an object, we can only have one argument, unlike a component.
class reg_seq extends uvm_object_name ;
`uvm_object_utils(reg_seq)
// default constructor for sequence
function new(string name = "reg_seq")
super.new(name);
endfunction
...
...
endclass
3. Component and object creation
The create() method of the wrapper class is used to create objects for the uvm_object and uvm_component classes.
- Component instances and component hierarchy are created in the build phase.
- uvm_object are created in run time, so create UVM objects in the run phase.
Syntax for component creation
handle_name = class_name :: type_id :: create("name",parent)
Syntax for object creation
handle_name = class_name :: type_id :: create("name")
- Example
`include "uvm_macros.svh"
import uvm_pkg::*;
//Extend seq from uvm_sequence_item
class seq extends uvm_sequence_item;
//a is rand variable and bit data type
rand bit a;
//UVM Factory Registration Macro
`uvm_object_utils_begin(seq)
`uvm_field_int(a,UVM_DEFAULT)
`uvm_object_utils_end
//constructor Method
function new(input string name = "seq");
super.new(name);
endfunction
endclass
module top;
seq s1;
//Within initial
initial
begin
//create an instance of seq using factory create()
s1= seq::type_id::create("s1");
//repeating 5 times using repeat
repeat(5)
begin
//using `uvm_info to display
`uvm_info("INFO","factory is created by using create method",UVM_NONE);
void'(s1.randomize());
s1.print();
end
end
endmodule
` Example.1 - Factory registration`
Github lab code link https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_SiliconCrew/factory_method/creat_method/factory_creation_code.sv
Github log code link https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_SiliconCrew/factory_method/creat_method/factory_creation_log.log
In the above example, trying to create a factory method by using the create method. we extend the class name by seq by using UVM inbuild library uvm_sequence_item and after that initializing the Factory registration Macro. Then declaring the constructor method.
s1 is the handle of the seq class. By using the following syntax, created the Factory method
handle_name= class_name::type_id::create("handle_name");
then class_handle.print is used to print the output.
- output snap

output.1 - output for factory creation and randomizing some transactions
In the above output, we created a factory using the create method and displayed some random values in 5 iterations.
Why do we need factory registration in UVM?
The factory requires knowledge of every class type that is produced within the testbench through a procedure known as registration. With the help of certain UVM macros classes can be registered with the factory, as well as methods that allow derived types to override certain types and instances of class objects.
- Example
Example for object creation using new constructor
`include "uvm_macros.svh"
import uvm_pkg::*;
//Extend seq from uvm_sequence_item
class seq extends uvm_sequence_item;
//a is rand variable and bit data type
rand int a;
//UVM Factory Registration Macro
`uvm_object_utils_begin(seq)
`uvm_field_int(a,UVM_DEFAULT)
`uvm_object_utils_end
//constructor Method
function new(input string name = "seq");
super.new(name);
endfunction
//constraint Method
constraint cons1{a inside {[5:10]};}
endclass
//Extend extend_seq from seq;
class extend_seq extends seq;
//UVM Factory Registration
`uvm_object_utils(extend_seq);
//constructor Method
function new (input string name="extend_seq");
super.new(name);
endfunction
//constraint method
constraint cons2 {a inside {9};}
endclass
module top;
seq s1;
extend_seq s2;
function void build();
void'(s1.randomize());
s1.print();
endfunction
//Within initial
initial
begin
//create an instance of seq using factory new()
s1=new();
//repeating 5 times using repeat
repeat(5) begin
//using `uvm_info to display
`uvm_info("B_INFO","1...factory is created by using create method",UVM_NONE);
build ();
end
factory.set_type_override_by_type(seq::get_type(),extend_seq::get_type());
repeat(5) begin
//using `uvm_info to display
`uvm_info("A_INFO","2...factory is created by using new method",UVM_NONE);
s1=new();
build();
end
end
endmodule
Example.2 - Component creation using new constructor
GitHub lab code link https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_SiliconCrew/factory_method/new_method/factory_new_code.sv
Github log code link https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_SiliconCrew/factory_method/new_method/factory_new_log.log
In the above example, here trying to create a factory method by using the new method. we extend the class name seq by using UVM inbuild library uvm_sequence_item and after that initializing the Factory registration Macro. then we declare the constructor method.
s1 is the handle of the seq class we use this syntax to create the Factory method
handle_name= class_name::type_id::create("handle_name");
then class_handle.print using to print the output. Trying to over-riding the parent class with the child class but here we are using only a new method so we can't override the factory things, this is the main drawback of the new method,so that's we will be moving to factory registration with create method.
- output

output.2 - output for object creation by using new constructor
In the above output, creating the factory we were using the new method. we declared 2 constraints, the 1st constraint is declared in the parent class and the second constraint is declared in the child class i.e., the 5 to 10 range in constraint 1, and the 2nd constraint is only 9. If the override is possible then it constraint solver gives 9 but it is not the case here, the other numbers were also given as we used new method.
4. Factory Override

Fig.1 - Over-riding types
Factory override means to override the base class with the child class. Factory overriding helps exchange the test bench's behaviour by substituting one class for another when it is constructed without having to edit or recompile the test bench code.
Using the polymorphism concept, the factory override mechanism returns a derived type handle using a base type handle. This means when the create method is being called for the base class type, uvm_factory will return a pointer to an object of a derived class type.
Note: The factory override ways are applicable for both uvm components and uvm objects.
There are two ways to override the factory -
1. Global Override
2. Instance Override
1.Global Override
In a global override, a substitute component class type is created instead of an original component class in the testbench hierarchy. It applies to all instances of that component type. (It means the changes done by type override are reflected for the entires testbench)
There are two methods for a global override -
1.1. set_type_ovrrride_by_type
Syntax
set_type_override_by_type(original_type::get_type(),substitute_type::get_type(),replace=1);
//replace =1 is the default value
1.2. set_type_override_by_name
Syntax
set_type_override_by_name (string original_type_name, string override_type_name, bit replace = 1)
2. Instance Override
Instance override does override only specified components in the uvm Testbench hierarchy.
There are two methods of instance override.
2.1.set_inst_override_by_type
Syntax
set_inst_override_by_type (uvm_object_wrapper original_type,uvm_object_wrapper override_type string full_inst_path);
2.2. set_inst_override_by_name
Syntax
set_inst_override_by_name (string original_type_name,string override_type_name,string full_inst_path);
- Example
Let's take an example of Global Override for better understanding.
`include "uvm_macros.svh"
import uvm_pkg::*;
//Extend seq from uvm_sequence_item
class seq extends uvm_sequence_item;
//a is rand variable and bit data type
rand int a;
//UVM Factory Registration Macro
`uvm_object_utils_begin(seq)
`uvm_field_int(a,UVM_DEFAULT)
`uvm_object_utils_end
//constructor Method
function new(input string name = "seq");
super.new(name);
endfunction
//constraint Method
constraint cons1{a inside {[5:10]};}
endclass
//Extend extend_seq from seq;
class extend_seq extends seq;
//UVM Factory Registration
`uvm_object_utils(extend_seq);
//constructor Method
function new (input string name="extend_seq");
super.new(name);
endfunction
//constraint method
constraint cons2 {a inside {9};}
endclass
module top;
seq s1;
extend_seq s2;
//Within initial
initial
begin
//create an instance of seq using the factory create method
s1=seq::type_id::create("s1");
//s1=new();
//repeating 5 times using repeat
repeat(5) begin
//using `uvm_info to display
`uvm_info("A_INFO","1...before global_overriding ",UVM_NONE);
void'(s1.randomize());
s1.print();
end
factory.set_type_override_by_type(seq::get_type(),extend_seq::get_type());
s1=seq::type_id::create("s1");
// s1=new();
repeat(5) begin
//using `uvm_info to display
`uvm_info("B_INFO","2...after factory overriding by using global_override ",UVM_NONE);
void'(s1.randomize());
s1.print();
end
end
endmodule
Example.3 - Global Over-riding by using factory registration
In the above example, we were doing global overring, we extend the class name seq by using UVM inbuild library is uvm_sequence_item and after that initialized the Factory registration Macro and in this class, we wrote constraint its range from 5 to 10 values. another class name is extend_seq is extends from the seq, In this class, we wrote constraint a=9 if factory override is done it gives the output as 9. this is done by using their global overriding and we followed syntax is factory.set_type_override_by_type(seq::get_type(),extend_seq::get_type());
- output snap

output.3 - output for Global over-riding by type
In the above output, creating the factory we were using the create method and overriding the things by using the global override method. we declared 2 constraints, the 1st constraint is displayed in the 5 to 10 range and the 2nd constraint is only 9. If the override is correct it displays the 9. see the last 3 iterations of output it displays the output as 9.
GitHub lab code link https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_SiliconCrew/factory_method/override/global_ov/global_override_code.sv
GitHub log code link https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_SiliconCrew/factory_method/override/global_ov/global_override_log.log