uvm_comparer is the standalone class used to set a policy for doing comparisons and determines how miscompares are counted. Every uvm_object instance has a compare() method for performing comparisons with another object. A policy object can be passed along to set parameters like depth of comparison, verbosity, maximum number of miscompares etc - an extra layer of flexibility. uvm_comparer also has a set of comparison methods for integers, strings, real numbers and objects.

Note that the number of miscompares is stored in an internal variable called "result", which gets incremented upon every such occurrence. Hence, if you are using the same object to compare two different items, the number of miscompares shown in the end might not be correct. It is advised to clear the "result" variable for every new comparison. This is only valid if you are directly using an object like in the example shown below.

When the uvm_comparer object is passed onto uvm_object::compare() method, the comparison policy will be set, and result will be cleared. If no uvm_comparer object is passed along, then it will take the default global level uvm_comparer policy object.



Example

This example will build upon the How to use uvm_printer set of data objects.


class base_test extends uvm_test;
   `uvm_component_utils (base_test)

   my_data obj0, obj1;
   derivative dv0, dv1;

   uvm_comparer uc0;

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

   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      obj0 = my_data::type_id::create ("obj0");
      obj1 = my_data::type_id::create ("obj1");
      uc0 = new();
   endfunction

   virtual task run_phase (uvm_phase phase);

      cfg_comparer();
      // Do not use the same uvm_compare object to do multiple comparisons, like shown below 
      // The example is a demonstration of the different methods of uvm_compare
      // NOTE: There's an internal variable "result" that stores the number of miscompares.
      // This variable will continue to be incremented for every mismatch, until cleared manually 

      `uvm_info ("COMPARE", "Trying out compare_field", UVM_MEDIUM)
      uc0.compare_field ("compare_field1", 7, 7, 2);            // pass
      uc0.compare_field ("compare_field2", 8'd45, 8'd8, 2);     // fail

      `uvm_info ("COMPARE", "Trying out field_int", UVM_MEDIUM)
      uc0.compare_field_int ("field_int1", 64'hface_deaf_feed_cafe, 64'hfabe_deaf_feed_cafe, 64);  // fail 
      uc0.compare_field_int ("field_int2", 64'habcd_ef12_3456_7890, 64'habcd_ef12_3456_7890, 64);  // pass
      
      uc0.compare_field_int ("field_int3", 64'hface_deaf_feed_cafe, 64'h7ace_deaf_feed_cafe, 63);  // pass 
      uc0.compare_field_int ("field_int4", 64'hface_deaf_feed_cafe, 64'h8abe_deaf_feed_cafe, 64);  // fail 

      uc0.compare_field_int ("field_int5", 68'hbbbb_face_deaf_feed_cafe, 68'haaaa_8abe_deaf_feed_cafe, 68); //  won't work; nothing happens
      uc0.compare_field ("field", 68'hb_face_deaf_feed_cafe, 68'haa_8abe_deaf_feed_cafe, 68); // fail: will work with field, because size > 64

      `uvm_info ("COMPARE", "Trying out compare_object", UVM_MEDIUM)
      void'(obj0.randomize());
      void'(obj1.randomize());
      uc0.compare_object ("object1", obj0, obj1);  // fail
      obj1.copy (obj0);
      uc0.compare_object ("object2", obj0, obj1);  // pass

      `uvm_info ("COMPARE", "Trying out compare_string", UVM_MEDIUM)
      uc0.compare_string ("string1", "Hello", "World");   // fail
      uc0.compare_string ("string2", "Hello", "Hello");   // pass

      
      // Proper Usage: Set the configuration for uvm_comparer and pass it to compare()
      // The "result" variable is cleared before comparison starts within uvm_object::compare()
      obj0.name = "Apple";
      obj0.m_format0.m_color.fav = "magenta";
      obj0.m_format0.m_color.unfav = "yellow";

      obj1.name = "Orange";
      obj1.m_format0.m_color.fav = "magenta";
      obj1.m_format0.m_color.unfav = "green";

      cfg_comparer();
      void'(obj0.randomize());
      obj1.compare (obj0, uc0);

      // randomize and compare again
      void'(obj0.randomize());
      obj1.compare (obj0, uc0);
      

   endtask

   virtual function cfg_comparer();
      uc0.show_max = 20;     // total number of miscompares to be printed
      uc0.verbosity = UVM_MEDIUM;
   endfunction

endclass
 Simulation Log
UVM_INFO @ 0: reporter [RNTST] Running test base_test...
UVM_INFO ./tb/test_pkg.sv(43) @ 0: uvm_test_top [COMPARE] Trying out compare_field
UVM_INFO @ 0: reporter [MISCMP] Miscompare for compare_field2: lhs = 'h1 : rhs = 'h0
UVM_INFO ./tb/test_pkg.sv(47) @ 0: uvm_test_top [COMPARE] Trying out field_int
UVM_INFO @ 0: reporter [MISCMP] Miscompare for field_int1: lhs = 'hfacedeaffeedcafe : rhs = 'hfabedeaffeedcafe
UVM_INFO @ 0: reporter [MISCMP] Miscompare for field_int4: lhs = 'hfacedeaffeedcafe : rhs = 'h8abedeaffeedcafe
UVM_INFO @ 0: reporter [MISCMP] Miscompare for field: lhs = 'hbfacedeaffeedcafe : rhs = 'ha8abedeaffeedcafe
UVM_INFO ./tb/test_pkg.sv(57) @ 0: uvm_test_top [COMPARE] Trying out compare_object
UVM_INFO @ 0: reporter [MISCMP] Miscompare for object1.data: lhs = 'h5a : rhs = 'h47
UVM_INFO @ 0: reporter [MISCMP] Miscompare for object1.addr: lhs = 'h1 : rhs = 'h2
UVM_INFO @ 0: reporter [MISCMP] Miscompare for object1.m_format0.header: lhs = 'hb : rhs = 'h2
UVM_INFO @ 0: reporter [MISCMP] Miscompare for object1.m_format0.footer: lhs = 'h0 : rhs = 'h7
UVM_INFO @ 0: reporter [MISCMP] Miscompare for object1.m_format0.body: lhs = 'h1 : rhs = 'h2
UVM_INFO @ 0: reporter [MISCMP] Miscompare for object1.m_format0.m_color.color: lhs = 'h8 : rhs = 'h2
UVM_INFO @ 0: reporter [MISCMP] 10 Miscompare(s) for object obj1@2722 vs. obj0@2687
UVM_INFO @ 0: reporter [MISCMP] 10 Miscompare(s) for object obj1@2722 vs. obj0@2687
UVM_INFO ./tb/test_pkg.sv(64) @ 0: uvm_test_top [COMPARE] Trying out compare_string
UVM_INFO @ 0: reporter [MISCMP] Miscompare for string1: lhs = "Hello" : rhs = "World"
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.data: lhs = 'h5a : rhs = 'hee
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.addr: lhs = 'h1 : rhs = 'h2
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.header: lhs = 'hb : rhs = 'hf
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.body: lhs = 'h1 : rhs = 'h2
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.m_color.color: lhs = 'h8 : rhs = 'h7
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.m_color.enable: lhs = 'h0 : rhs = 'h1
UVM_INFO @ 0: reporter [MISCMP] 6 Miscompare(s) for object obj0@2687 vs. obj1@2722
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.data: lhs = 'h5a : rhs = 'h2d
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.addr: lhs = 'h1 : rhs = 'h3
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.header: lhs = 'hb : rhs = 'h9
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.footer: lhs = 'h0 : rhs = 'h6
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.enable: lhs = 'h1 : rhs = 'h0
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.m_color.color: lhs = 'h8 : rhs = 'h0
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.m_color.enable: lhs = 'h0 : rhs = 'h1
UVM_INFO @ 0: reporter [MISCMP] 7 Miscompare(s) for object obj0@2687 vs. obj1@2722

--- UVM Report catcher Summary ---