Log file for uvm object type class

I have a requirement to create separate log files of class model extended from uvm object. As uvm object doesn’t inherit from report handler, I am trying to use creator handle for the same as shown below. However I am not getting desired results.


class my_obj extends uvm_object;
  `uvm_object_utils(my_obj);

  function new(string name = "");
    super.new(name);
    tID = get_type_name();
    tID = tID.toupper();
  endfunction

  function void configure(uvm_component creator = null);
    if(creator != null) begin
      string hier_s;
      string creator_s;  

      creator_s = creator.get_full_name();
      hier_s = { creator_s, ".", get_full_name(), ".log" }
      log = $fopen(hier_s, "w");

      if(!log) begin
        `uvm_fatal(tID, {hier_s, "can't open to write"});
      end

      creator.set_report_id_file(tID, log);
    end
   
  endfunction

  function void display();
    `uvm_info(tID, "this print goes to log file", UVM_HIGH);
  endfunction

  function void end_of_sim();
    if(log) $fclose(log);
  endfunction

  local int log = -1;
  protected string tID;

endclass

class my_comp extend uvm_component;
  `uvm_component_utils(my_comp);

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

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    obj = my_obj::type_id::create("obj");
    obj.configure(this);
  endfunction

  function void report_phase();
    obj.end_of_sim();
  endfunction

  function void display();
    obj.display();
  endfunction

  protected my_obj obj;
endclass

module try;

  my_comp comp;

  initial begin
    comp = my_comp::type_id::create("comp", uvm_root::get());
    comp.display();

  end

endmodule


Here, comp.obj.log file is getting created but instead of display message directed to file it’s still coming on console.
Am I missing something here?

In reply to bhupeshpaliwal:

In reply to chr_sue:
I did declare tID. Also I am using same tID to set report file id.


protected string tID;
..
creator.set_report_id_file(tID, log);

As a first remark. You are writing only data to the log-file with the UVM_VERBOSITY = UVM_HIGH.
The default verbosity is UVM_MEDIUM. Do you simulate with the verbosity UVM_HIGH?

In reply to chr_sue:
Yes ran with UVM_HIGH.
I have an impression the uvm_info uses a global reporting mechanism so once we manage to set report id file with ID and file handle … irrespective whether uvm info gets called by uvm_component or uvm_object type classes, it won’t matter.

In reply to bhupeshpaliwal:
I have tried to visualize your problem. Please find the code below:

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

class my_obj extends uvm_object;
  `uvm_object_utils(my_obj);

  local int log = -1;
  string tID;
 
 
  function new(string name = "");
    super.new(name);
  endfunction
 
  function void build_phase(uvm_phase phase);
    tID = get_type_name();
    tID = tID.toupper();
    `uvm_info(get_type_name(), $sformatf("my_comp build_phase"), UVM_MEDIUM)
    `uvm_info(get_type_name(), $sformatf("tID = %s", tID), UVM_MEDIUM)
  endfunction

  function void configure(uvm_component creator = null);
    if(creator != null) begin
      string hier_s;
      string creator_s;  
 
      creator_s = creator.get_full_name();
      `uvm_info(get_type_name(), $sformatf("creator = %s", creator_s), UVM_MEDIUM)
      hier_s = { creator_s, ".", get_full_name(), ".log" };
      `uvm_info(get_type_name(), $sformatf("filename = %s", hier_s), UVM_MEDIUM)
      log = $fopen(hier_s, "w");
 
      if(!log) begin
        `uvm_fatal(tID, {hier_s, "can't open to write"});
      end
 
     `uvm_info(get_type_name(), $sformatf("my_obj tID = %s", tID), UVM_MEDIUM)
      creator.set_report_id_file(tID, log);
      creator.set_report_id_action(tID, UVM_LOG);
    end
 
  endfunction
 
  function void disp(string arg);
    `uvm_info(arg, "this print goes to log file", UVM_HIGH)
  endfunction
 
  function void end_of_sim();
    if(log) $fclose(log);
  endfunction
 
endclass
 
class my_comp extends uvm_component;
  `uvm_component_utils(my_comp);

  my_obj obj;
  string ID;
 
  function new(string name = "", uvm_component parent = null);
    super.new(name, parent);
  endfunction
 
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    obj = my_obj::type_id::create("obj");
    `uvm_info(get_type_name(), $sformatf("my_comp build_phase"), UVM_MEDIUM)
    obj.configure(this);
    ID = obj.tID;
    `uvm_info(get_type_name(), $sformatf("my_compID = %s", ID), UVM_MEDIUM)
  endfunction

  function void report_phase(uvm_phase phase);
    obj.end_of_sim();
  endfunction
 
  function void disp(string arg);
    obj.disp(arg);
  endfunction
 
endclass
 
module try;
import uvm_pkg::*;
`include "uvm_macros.svh"
 
  my_comp comp;
  initial begin
    run_test("my_comp");
    comp.disp(comp.ID);
    `uvm_info("top", $sformatf("comp = %p", comp), UVM_MEDIUM)
    `uvm_info("top", $sformatf("comp ID = %s", comp.ID), UVM_MEDIUM)
   end 
endmodule


You have to different types of dynaic obejcts (classes) in your example, i.e. uvm_component and uvm_object.
uvm_component classes are used to build yout tesbench. These objects are constructed at runtime 0.
The 2nd class type is uvm_object. This type is used to create sequence_items and sequences. They do not belong to the hierarchy of your testbench And you cannot simply share data between the different types. You are trying this and you are failing. Please see the simulation log-file.

In reply to chr_sue:

Thanks a lot for replying back. Indeed I do understand uvm_compnent and uvm_objects have different usage from UVM methodology perspective.
Unlike uvm_component, uvm_objects doesn’t have any phasing … which I required in my class(i.e. my_obj) hence extended from uvm_object.


class my_obj extends uvm_object;
  `uvm_object_utils(my_obj);
 
  local int log = -1;
  string tID;
 
  function new(string name = "");
    super.new(name);
  endfunction
 
  function void build_phase(uvm_phase phase);
    tID = get_type_name();
    tID = tID.toupper();
    `uvm_info(get_type_name(), $sformatf("my_comp build_phase"), UVM_MEDIUM)
    `uvm_info(get_type_name(), $sformatf("tID = %s", tID), UVM_MEDIUM)
  endfunction
 
  function void configure(uvm_component creator = null);
 ...

From your example: build_phase function NEVER get’s called for my_obj as uvm_object doesn’t have build_phase at all. It’s like any other user defined function like configure.

While I do understand that probably I am doing exactly the UVM-way … but since UVM by default involves global reporting mechanism i.e. uvm_info call either from uvm_component or uvm_object should have resulted in same results … which isn’t the case.
I will explore a bit in uvm report handler to understand more.

In reply to bhupeshpaliwal:

You are being led in the wrong direction. And your vision is obscured by by the use of macros.

When you use the `uvm_info macro, it calls uvm_report_info which is both a method of uvm_report_object and a global function. If you call uvm_report_info from a class not derived from uvm_report_object, like uvm_object, it picks up the the global function. uvm_component is derived from uvm_report_object.

What you should do is extend my_obj from uvm_report_object, not uvm_object. Every instance of a class derived from uvm_report_object has an instance of uvm_report_handler, and that is where al the report settings get stored. Every instance of a class derived from uvm_report_object can have unique report settings.

It seems like you are try to use the uvm_report_handler from my_comp. It is possible to do that using a different set of macros:`uvm_info_context(arg, “this print goes to log file”, UVM_HIGH, creator_s). But realize these settings get applied to the component instance which get shared by all the other objects created by my_comp.

In reply to bhupeshpaliwal:

I made a few additional attempts, but did not succeed to write to the logfile.
And I thought a lot about your objective. Is this exampls a theoretical example or what is it?
If you want to use constructs like this in a project it violates one of the basic UVM implementation rules: “write your code as simple as possible. A 3rd person should understand your implementation without big effort”.

In reply to chr_sue:
Thanks to dave, I did managed to figure it out.
To be honest, it’s not theoretical example … I have prepared a behavorial model and thus not intended to use any phasing aspect(which we get in uvm_component) and hence started extending my class from uvm_object. Intention was model to have separate log file.

As per dave suggestion, I tried to understand a bit and came up with following, though still has scope of improvement but works for time-being.


class my_obj extends uvm_report_object;
  `uvm_object_utils(my_obj);
 
  function new(string name = "");
    super.new(name);
    tID = get_type_name();
    tID = tID.toupper();
  endfunction
 
  function void configure(uvm_component parent = null);
    string hier_s;
    uvm_verbosity verb;
    
    if(parent != null) begin
      hier_s = parent.get_full_name();
    end else begin
       uvm_coreservice_t cs = uvm_coreservice_t::get();
       parent = cs.get_root();
    end

    hier_s = (hier_s == "") ? hier_s : { hier_s, "." };

    hier_s = { hier_s, get_full_name(), ".log" }
    log = $fopen(hier_s, "w");
 
    if(!log) begin
      `uvm_fatal(tID, {hier_s, "can't open to write"});
    end
      
    verb = uvm_verbosity'(parent.get_report_verbosity_level());
    this.set_report_verbosity_level(verb);
    this.set_report_id_action(tID, UVM_LOG);
    this.set_report_id_file(tID, log);
    
 
  endfunction
 
  function void display();
    `uvm_info(tID, "this print goes to log file", UVM_HIGH);
  endfunction
 
  function void end_of_sim();
    if(log) $fclose(log);
  endfunction
 
  local int log = -1;
  protected string tID;
 
endclass
 

module try;
 
  my_obj obj;
 
  initial begin
    obj = my_obj::type_id::create("obj");
    obj.configure();
    obj.display();
    obj.end_of_sim(); 
  end
 
endmodule

In reply to dave_59:
Thanks dave, I did managed to use uvm_report_object to get desired results