Issues with do_print() method?

Hi,

I see a weird issue where the sprint() call printing the fields from other interface verification component’s (IVC) sequence item. I have methods defined in each of the IVC’s as below:



function string my_item::convert2string ();
  string  str;

  str = $sformatf("\n%s data_avail   : \t0x%0x\n", str,m_data_avail);
  str = $sformatf("%s mce_go           : \t0x%0x\n", str,m_mce_go);
  str = $sformatf("%s mce_config_mode  : \t0x%0s\n", str,m_mce_config_mode.name());
  str = $sformatf("%s trans_delay      : \t0x%0x\n", str,delay);

  return str;

endfunction : convert2string

function void do_print (uvm_printer printer);
  if(printer.knobs.sprint == 1) begin
    printer.m_string = convert2string();
  end
endfunction : do_print


Don’t understand what could be wrong here to mess up with the print. Printing using $display does print the values in the monitor correctly. However the sprint() call is screwing up the print.

Can someone explain and also the above method of do_print() is correct or not?

Thanks in advance,
Madhu

In reply to mseyunni:

Don’t understand what could be wrong here since we can’t run this code, and you didn’t show us what you saw versus what you were expecting. See How to create a Minimal, Reproducible Example - Help Center - Stack Overflow and How do I ask a good question? - Help Center - Stack Overflow

In reply to mseyunni:

Old post, but I have a similar problem: In some cases, the return value from tr.sprint() is from a totally different transaction type (i.e. not from tr). It works as expected if I call tr.sprint(my_tr_printer) instead of using the default printer (i.e. no sprint argument). Basically, I work around this problem by using a different printer instance for each transaction type when I call sprint from classes that deal with different transaction types (e.g. vseq, scoreboard). I don’t like this solution but it works.

In my case, the expected tr does NOT have a do_print() or convert2string() implementation; it relies on the field util macro for printing. The “bad” transaction that’s showing up in the middle of my message DOES have both of those methods implemented, similar to your example, and does NOT use the field util macros for printing.

Once the “bad” transaction is printed (intentionally), it sets printer.mstring and I think that’s what’s messing up the results in a subsequent tr.sprint() call. If printer.m_string is set, then sprint uses it. If not, then it returns printer.emit. Maybe it’s bad practice to mix-and-match setting printer.mstring in one transaction type and using the field macros in another, but the macros are handy and consistent when I don’t need a fancy message format implemented with convert2string.

Another solution would be to call convert2string()directly instead of indirectly via sprint()->do_print()->convert2print(). That only works if you know which transactions implemented convert2string() or if you implement it for all transactions.

I’d like to hear other suggestions for how to prevent this message mixup when using sprint().

In reply to npratt:

If you are using the field macros and have implemented the do_print manually the last one has the precedence.

Im generating my UVM Frameworks automatically, i.e. each seq_item definition has a do_print method like this:

function void do_print(uvm_printer printer);
  if(printer.knobs.sprint == 0) begin
    `uvm_info(get_type_name(), convert2string(), UVM_MEDIUM)
  end else begin 
    printer.m_string = convert2string();
  end
endfunction : do_print

In all my projects I did (20+) I have never faced an issue like you are describing.

In reply to chr_sue:

Do you also define convert2print in ALL your sequence items? Do you use the field macros for printing in ALL, NONE, or SOME of your sequence items? I’m trying to pinpoint what we are doing differently.

I only define do_print (same as your example) for a fail_inject transaction which also has convert2string defined. The other sequence items in our testbench only use the field macro for printing (no do_print or convert2string). If ALL my sequence items defined the same do_print (as in your example), I probably wouldn’t have the problem because m_string would be updated for each sprint call. If I really need to put that code in ALL sequence items, even when I just want to use the field macros, why isn’t it in the uvm base class?

I have faced this issue in numerous projects. It always comes back to having the sequence item with do_print/convert2string mistakenly inserted into a message that is using sprint on a transaction where only the field macros were used (no do_print or convert2print). Years ago, I also had problems when using the field macros and also adding more details with do_print, so I don’t mix-and-match those approaches anymore.

In reply to npratt:

Yes, I’m implementing also convert2string in all seq_items.
I use a UVM Framework generator which is doing the work for me
And I do not use field macros, because it is not recommended and I want to avoid critical situations.

I believe it is not a good idea not to define do_print and convert2string, because I want to see, what will be generated.