Confusion About uvm_void in UVM Hierarchy

I am a beginner in UVM and trying to understand the purpose of uvm_void.

From the hierarchy, I see:


uvm_void
   ↓
uvm_object
   ↓
other UVM classes

But I am confused because uvm_void is an empty class with no methods or variables.

So my questions are:

  • If uvm_void is completely empty, then why was it needed?

  • Why didn’t UVM architects directly make uvm_object the top/base class?

  • What is the actual difference between uvm_void and uvm_object apart from one being empty and the other having methods?

  • What real problem does uvm_void solve?

  • In what situation would uvm_void work differently from uvm_object?

  • Is this only for framework architecture flexibility, or is there an actual practical use case?

As a beginner, it feels like uvm_object could also work everywhere, so I am unable to relate the need for uvm_void.

As a beginner or even average user, there’s no need to comprehend uvm_void. It’s worth noting that many people criticized the creation of the uvm_void class, considering it unnecessary overhead. This UVM class was introduced to address the limitation of SystemVerilog OOP, which originated from Java, in casting a pointer to a void* type, unlike in C/C++. This ensures that objects remain type-safe.

Java does have a root class java.lang.Object from which everything extends. uvm_void was designed to mimic this structure. It would primarily be used when integrating two different base class methodologies.

I have one more doubt regarding the use of uvm_void in UVM.

For example:

class uvm_pool #(type KEY=int, T=uvm_void) extends uvm_object;

virtual class uvm_port_base #(type IF=uvm_void) extends IF;

Why did UVM use uvm_void here instead of uvm_object?

  • What practical issue would happen if uvm_object was used instead?

  • When should a UVM class use:

    • uvm_void

    • uvm_object

    • or a specific class type as a parameter?

  • Is uvm_void mainly used to allow non-uvm_object types/interfaces/classes as generic parameters?

I want to understand the architectural/design reason behind this choice.

uvm_void is redundant here because it will be overridden by any type including a non-class type. It’s unfortunate that there’s still a tool out there that doesn’t support parameters without a default assignment. This would force users to explicitly override the parameter when declaring a uvm_pool class