单例对象/singleton object只是类的单个对象。即使用户尝试创建多个新对象,也会返回相同的对象。允许创建单个对象的类称为singleton类。

在UVM中,uvm_root类只有一个实例。因此,它被称为单例类/singleton object。

1 Singleton Object Usage

当需要创建单个对象并希望限制用户创建另一个对象时,单个对象非常有用。例如,可以编写配置类,使其表现为单个类。

注:System Verilog和UVM没有单独的构造函数来创建单个对象。

【Note: System Verilog and UVM do not have a separate construct to create a singleton object.】

2 Singleton Object Example

在下面的示例中,同一个单例组件sc1和sc2有两个句柄,并且已经尝试创建两次对象。但在使用句柄sc2创建对象时,不会分配单独的内存,而sc2句柄指向使用句柄sc1分配的内存。

`include "uvm_macros.svh"
import uvm_pkg::*;

class singleton_comp extends uvm_component;
  static singleton_comp s_comp;
  rand bit [7:0] addr;
  rand bit [7:0] data;
  
  `uvm_component_utils_begin(singleton_comp)
    `uvm_field_int(addr, UVM_ALL_ON)
    `uvm_field_int(data, UVM_ALL_ON)
  `uvm_component_utils_end
  
  function new(string name = "singleton_comp", uvm_component parent = null);
    super.new(name, parent);
  endfunction
  
  static function singleton_comp create_singleton();
    if(s_comp == null) begin
      $display("creating new object as it found null");
      s_comp = new();
    end
    else $display("object already exist, separate memory will not be allocated.");
    return s_comp;
  endfunction
  
  task run_phase(uvm_phase phase);
    super.run_phase(phase);
  endtask
endclass

class base_test extends uvm_test;
  `uvm_component_utils(base_test)
  singleton_comp sc1, sc2;

  function new(string name = "base_test",uvm_component parent=null);
    super.new(name,parent);
  endfunction : new

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);

    // create singleton object
    sc1 = singleton_comp::create_singleton();
    assert(sc1.randomize());
    `uvm_info(get_type_name, $sformatf("Printing sc1 = \n%s",sc1.sprint()), UVM_LOW);
    
    // Trying to create another object but it won't be created
    sc2 = singleton_comp::create_singleton();
    `uvm_info(get_type_name, $sformatf("Printing sc2 = \n%s",sc2.sprint()), UVM_LOW);
  endfunction : build_phase
endclass

module singleton_example;
  initial begin
    run_test("base_test");
  end
endmodule

Output:

creating new object as it found null
UVM_INFO testbench.sv(46) @ 0: uvm_test_top [base_test] Printing sc1 = 
-------------------------------------------
Name            Type            Size  Value
-------------------------------------------
singleton_comp  singleton_comp  -     @349 
  addr          integral        8     'h90 
  data          integral        8     'ha6 
-------------------------------------------

object already exist, separate memory will not be allocated.
UVM_INFO testbench.sv(50) @ 0: uvm_test_top [base_test] Printing sc2 = 
-------------------------------------------
Name            Type            Size  Value
-------------------------------------------
singleton_comp  singleton_comp  -     @349 
  addr          integral        8     'h90 
  data          integral        8     'ha6 
-------------------------------------------
01-02 03:31