Why are UVM User-Defined Phase Classes Implemented as Singletons?

Hi everyone,

I’m trying to understand the design decision behind user-defined phases in UVM.

Most examples (and the built-in UVM phases) implement the custom phase class as a Singleton, for example by using a static get() method and a protected new() constructor.

My questions are:

  1. Why does UVM recommend or require user-defined phase classes to be Singleton?

  2. What would actually happen if I didn’t implement my custom phase as a Singleton and instead created phase objects using new()?

  3. Is there any issue with the phase scheduler, phase state, objections, or schedule graph if multiple instances of the same custom phase exist?

  4. Is the Singleton pattern a strict UVM requirement, or is it simply a recommended design pattern?

I’m looking for the reasoning from the UVM architecture and source code perspective (IEEE 1800.2-2020), rather than just “because all examples do it.”

I’d really appreciate explanations based on the UVM scheduler and uvm_domain/uvm_phase implementation.

Thanks!

It’s a requirement. This singleton pattern is used extensively throughout UVM because it establishes a single object that serves as a unique reference point for comparisons. In essence, you create an object whose handle represents an object type. This handle can be passed as an argument to methods and can be compared with other handles.

If you didn’t use a singleton, you’d be wasting resources because there’s no logical reason to have multiple objects of the same type. Additionally, you’d have to create a unique identifier for each type, and you wouldn’t be able to verify its uniqueness until runtime.