uvm_factory is used to create UVM objects and components and only one instance of the factory will be present in a simulation. User-defined objects and components (ones that you derive from
uvm_component) need to be registered with the factory via typedef or macro invocation. There are three basic operations to using the factory:
Register objects and components with the factory
When you create and derive a class from either
uvm_component, invoke the appropriate macro. These macros are required to ensure portability across different vendor's simulators. When register components, switch "object" with "component" in the below example.
/* Objects that are not parameterized */ class packet extends uvm_object; `uvm_object_utils (packet)` endclass /* Objects that are parameterized */ class packet #(type T=int, int WIDTH=64) extends uvm_object; `uvm_object_param_utils (packet #(T,WIDTH))` endclass
Design components such that they can be created from the factory
After registering with the factory, you can 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. In normal cases, here is how you would create a new instance of a class.
class myDriver extends uvm_driver; `uvm_component_utils (myDriver)` function new (string name = "myDriver", uvm_component parent=null); super.new (name, parent); endfunction endclass ... /* Normal way to instantiate, but you cannot override this instance from the top */ myDriver m_drv0 = new ("myDriver0", null); /* Now, you will use the factory to instantiate the driver class*/ myDriver m_drv0 = m_drv0::type_id::create ("m_drv0", this); ...