Sprint vs convert2string

Can anyone know what the difference between sprint and convert2string in UVM objects.
Which one should be used by users?

In reply to verif_learner:

convert2string is a simple user-defined mechanism for converting umm_objects to strings. You are responsible for all formatting. The print and sprint methods use printer policies to format the fields that have been registered with the uvm_field macros.

In reply to verif_learner:

Adding to what Dave said, printer policies allows you to separate the content of your message from the formatting of your message. With the benefit of easy and consistent formatting for simple data types. Compared to covert2string, this happens at the cost of either limiting your formatting to one of the predefined policy classes, or the added effort of defining your own custom policy. Although the field macros use this printer policy mechanism, you don’t have to use the field macros to take advantage of it.

I generally prefer the flexibility it provides, so I implement the do_print method. From the UVM docs:

class mytype extends uvm_object;
  data_obj data;
  int f1;
  virtual function void do_print (uvm_printer printer);
    super.do_print(printer);
    printer.print_field_int("f1", f1, $bits(f1), UVM_DEC);
    printer.print_object("data", data);
  endfunction

And then, in order to support both sprint() and convert2string() users, I implement convert2string() as:

  return ( sprint( uvm_default_printer ) );

From a usage perspective, since uvm_default_table_printer is also the uvm_default_printer, the following will result in a multi-line table formatted message.

`uvm_info( "ID", item.sprint(), UVM_MEDIUM )

Sometimes I want a one-line message, which I can do with:

`uvm_info( "ID", item.sprint( uvm_default_line_printer ), UVM_MEDIUM )

Often I do the following, which makes it easy to see when the driver starts and completes driving an item, but also makes the starting message both less noticeable and also distinctly different from the completion message.

driver loop:

  `uvm_info( "ID", { "Starting drive: ", item.sprint( uvm_default_line_printer ) }, UVM_FULL )

  // drive multi-cycle transaction

  `uvm_info( "ID", { "Completed driving\n", item.sprint() }, UVM_HIGH )