Search code examples
system-veriloguvm

How do I get overridden transaction item in UVM driver?


I'm trying to get the overridden transaction item in UVM driver. I made a UVM sequence item class which has multiple inherited classes.

class mem_seq_item extends uvm_sequence_item;
  //---------------------------------------
  //data and control fields
  //---------------------------------------
  rand bit [1:0] addr;
  rand bit       wr_en;
  rand bit       rd_en;
  rand bit [7:0] wdata;
       bit [7:0] rdata;
  
  //---------------------------------------
  //Utility and Field macros
  //---------------------------------------
  `uvm_object_utils_begin(mem_seq_item)
    `uvm_field_int(addr,UVM_ALL_ON)
    `uvm_field_int(wr_en,UVM_ALL_ON)
    `uvm_field_int(rd_en,UVM_ALL_ON)
    `uvm_field_int(wdata,UVM_ALL_ON)
  `uvm_object_utils_end
  
  //---------------------------------------
  //Constructor
  //---------------------------------------
  function new(string name = "mem_seq_item");
    super.new(name);
  endfunction
  
  //---------------------------------------
  //constaint, to generate any one among write and read
  //---------------------------------------
  constraint wr_rd_c { wr_en != rd_en; }; 
  
endclass

class child_seq_item extends mem_seq_item;
  //---------------------------------------
  //data and control fields
  //---------------------------------------
   rand bit [7:0] A;
   rand bit [7:0] B;
   rand bit [7:0] C;
  
  //---------------------------------------
  //Utility and Field macros
  //---------------------------------------
  `uvm_object_utils_begin(child_seq_item)
    `uvm_field_int(A,UVM_ALL_ON)
    `uvm_field_int(B,UVM_ALL_ON)
    `uvm_field_int(C,UVM_ALL_ON)
  `uvm_object_utils_end
  
  //---------------------------------------
  //Constructor
  //---------------------------------------
  function new(string name = "child_seq_item");
    super.new(name);
  endfunction
  
endclass

And I create the my_sequence

class my_sequence extends mem_sequence;
  
  child_seq_item  child_item;
  `uvm_object_utils(my_sequence)
   
  //--------------------------------------- 
  //Constructor
  //---------------------------------------
  function new(string name = "my_sequence");
    super.new(name);
  endfunction
  
  virtual task body();
    child_item = child_seq_item::type_id::create("child_item");

    `uvm_do(child_item)
     child_item.print();
  endtask
endclass

and tried to execute the my_sequence class in my_testclass .

class my_test extends mem_wr_rd_test;

  `uvm_component_utils(my_test)
  
  //---------------------------------------
  // sequence instance 
  //--------------------------------------- 
  my_sequence my_seq;

  //---------------------------------------
  // constructor
  //---------------------------------------
  function new(string name = "my_test",uvm_component parent=null);
    super.new(name,parent);
  endfunction : new

  //---------------------------------------
  // build_phase
  //---------------------------------------
  virtual function void build_phase(uvm_phase phase);
    set_type_override_by_type(mem_seq_item::get_type(), child_seq_item::get_type());
    super.build_phase(phase);

    // Create the sequence
    my_seq = my_sequence::type_id::create("my_seq");
  endfunction : build_phase
  
  //---------------------------------------
  // run_phase - starting the test
  //---------------------------------------
  task run_phase(uvm_phase phase);
    
    phase.raise_objection(this);
      my_seq.start(env.mem_agnt.sequencer);
    phase.drop_objection(this);
    
    //set a drain-time for the environment if desired
    phase.phase_done.set_drain_time(this, 50);
  endtask : run_phase
  
endclass 

But Problem is I can't get overridden transaction item in UVM driver.

class mem_driver extends uvm_driver #(mem_seq_item);

  function new (string name, uvm_component parent);
    super.new(name, parent);
  endfunction : new


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

  //---------------------------------------  
  // run phase
  //---------------------------------------  
  virtual task run_phase(uvm_phase phase);
    forever begin
      seq_item_port.get_next_item(req);
      drive(req);
      `DRIV_IF.addr <= req.addr;
      `DRIV_IF.addr <= req.B; //<=== B is not a class item.
      seq_item_port.item_done();
    end
  endtask : run_phase
  

  virtual task drive(input mem_seq_item trans );
    `DRIV_IF.wr_en <= 0;
    `DRIV_IF.rd_en <= 0;
    @(posedge vif.DRIVER.clk);
    
    `DRIV_IF.addr <= trans.A;

The error message I can't get the A item.

`DRIV_IF.addr <= trans.A;
                       |
xmvlog: *E,NOTCLM (mem_driver.sv,52|27): A is not a class item.

How can I get the overridden transaction item in UVM driver?


Solution

  • Since the driver is parameterized with a mem_seq_item and has no information about overridden transactions, you need to downcast the class variable to a type that would know about the override

    virtual task drive(input mem_seq_item trans );
       child_seq_item csi;
       `DRIV_IF.wr_en <= 0;
       `DRIV_IF.rd_en <= 0;
       @(posedge vif.DRIVER.clk);
        if ($cast(csi,trans)
        `DRIV_IF.addr <= csi.A;
    

    If the trans is not a child_seq_item, then you will need to decide what happens in that case.