How is uvm_component registered inside the uvm_factory? - system-verilog

I've recently started studying the UVM and have some difficulty understanding the component/object registration process with the factory. Specifically, I can't find what line of code does the actual registration.
Here is my thought/search process:
I've found that uvm_factory class has a register method which registers a proxy object of a given type
This proxy object is of uvm_component_registry class parameterized with the type of the initially desired component/object
Inside uvm_component_registry class there is a get method, which creates the proxy object me and registers it with the factory via factory.register(me) call
In UVM Cookbook it says that every uvm_component should be registered with the factory by using the uvm_component_utils macro, which expands to the following code snippet:
typedef uvm_component_registry #(T,`"S`") type_id;
static function type_id get_type();
return type_id::get();
endfunction
virtual function uvm_object_wrapper get_object_type();
return type_id::get();
endfunction
virtual function string get_type_name ();
return type_name;
endfunction
So, here I come to the root of the problem. Inside the user class extended from the uvm_component class we have only the uvm_component_utils macro, which doesn't call the get method of the uvm_component_registry. Also there are no get method calls before the build phase during which we are creating the necessary class object using the factory. It certainly works, which means that our class has been registered. The question is - how? Are there some implicit get method calls?

On the contrary, because the `uvm_component_utils macro adds
typedef uvm_component_registry #(T,`"S`") type_id;
That parameterized class has a static variable with a declaration initialization
local static this_type me = get();
This calls get() without ever having to construct the uvm_component_registry class because it is a specialization of the class. You might want to read my DVCon paper: Using Parameterized Classes and Factories: The Yin and Yang of Object-Oriented Verification, or watch my short course on SystemVerilog OOP for UVM Verification. The go into detail how the UVM implements the Factory Design Pattern in system-verilog

Related

Is there an empty data class in SystemVerilog that is similar to "Object" in Java?

I was wondering if SystemVerilog has a generic class handler similar to how Java has an "Object" class or how C has a void*?
If so, what is it called? What I'm trying to do is have a class that when it is instantiated is passed a defined object, however it could be any object. So, I'm hoping that I can have an empty handler to this unknown data class (or generic) and I'm hoping that I don't have to create an empty data class and use one that is already part of the SystemVerilog library.
I should add that I'm not using UVM or any other methodologies, otherwise I would have just started from a uvm_component or uvm_object.
Java's Object class is the root base class of all classes. There is no such root class in SystemVerilog.
The UVM's uvm_object provides the functionality you are looking for and I suggest using it if for nothing else.

UVM: Why is get_type_name() not static?

Please consider this code...
virtual class SomeThing extends uvm_pkg::uvm_object;
`uvm_object_utils(SomeThing)
...
endclass
class MyThing extends SomeThing#(MyTransaction);
`uvm_object_param_utils(MyThing)
function new(string name = "MyThing");
super.new(name);
`uvm_info(get_name(), {"Created a ", get_type_name(),
" using transactions of type: ",
MyTransaction::get_type_name()}, // <--
UVM_LOW)
endfunction
...
endclass: MyThing
My problem is tagged with the <--. That's illegal because get_type_name() is not a static method and cannot be used with the scope resolution operator ::. (Both Synopsys and Cadence simulators complain similarly.)
Why isn't this method static? It feels wrong to reach around the accessor method to read the "const static string" that holds the value I want.
Thanks!
get_type_name isn't intended to print the name of a type. Its intention is to print the name of the type of a given object instance.
get_type_name is a virtual function. The intention behind a virtual function is to support polymorphism. If we were to have a variable of type uvm_object (where get_type_name is first defined), we could store objects of any sub-class of uvm_object in it. If we were to call get_type_name on the object, we would get the name of the object's type, without this code knowing anything about the type of this object at compile time.
Polymorphism makes it possible to write code that is generic, in that it can work with any concrete object type, as long as that type is a sub-type of something this code "understands".

Interface or class as method (or constructor) parameter

Why do I have class or interface passed as a method parameter in a class? I don't get that concept. For example:
Declaration:
public void doSomething (Class yourClass){}
Calling the method:
doSomething(yourClass);
What is the benefit? Is there an alternative? I can't call methods for yourClass anyway, for example: doSomething(yourClass.someMethod()) or doSomething(yourClass) and then yourClass.someMethod() are both invalid.
There's several possibilites, depending on the particular language. doSomething(Class) could...
Instantiate and return a Class generator.
Create an object or service to track or otherwise interact with one or more Class objects.
Return useful information about Class (e.g. via reflection).

Can parameters from a parametrized class be used in external function definitions?

Say I have a parametrized class foo and in it a simple setter.
class foo #(type T = int);
T member;
extern function T get_member();
endclass
If I try to define this function outside of class scope, I get an unknown type error for T.
function T foo::get_member();
return member;
endfunction
Fair enough, you'd get the same error in C++ (from which SV seems to have inherited much of the template/parametrization mechanism). So, in C++, you solve this by providing the template declaration before your function definition, so said template can be recognized by the compiler. Something like this:
template <typename T>
function T foo::get_member();
return member;
endfunction
Does a similar mechanism exist in SystemVerilog, and if so, what is it? If it doesn't then it's pretty clear I must define all my parametrized functions/tasks within the class body.
Set the scope to access the parameter type, change T to foo::T in the external function definition.
function foo::T foo::get_member();
return member;
endfunction
Working example here

How to declare type for a class method in Delphi?

How to declare type for a class procedure, for example
type
TTest = class
procedure Proc1;
class procedure Proc2;
class procedure Proc3; static;
end;
TProc1 = procedure of object;
TProc2 = ???;
TProc3 = ???;
TProc2 = procedure of object;
A class method still has a Self pointer. It's the class rather than the instance.
An interesting consequence of this is that it provides a way to implement event handlers without having to instantiate an object. For instance, you could use a class method of a class that that is never instantiated as a way to provide event handlers for the global Application object.
TProc3 = procedure;
A static class method has no Self pointer. It is assignment compatible with a plain procedural type.
Static class methods can be used as an alternative to globally scoped procedures. This does allow you to put such methods in a namespace, that of the class, and so avoid polluting the global namespace.
Take care when implementing static class methods that you do not call virtual class methods. Such calls are bound statically at compile time because the lack of a Self pointer means that dynamic polymorphic binding at runtime is not possible. Rather disappointingly the compiler fails to warn of this and so you do need to keep your wits about you.