UVM Basic Question

Hi guys, I have a basic question. A UVM example on one of the sites defines the sequence class as follows, (question is indicated by arrows):

class mem_sequence extends uvm_sequence#(mem_seq_item);
   
  `uvm_sequence_utils(mem_sequence,mem_sequencer)
   
  //Constructor
  function new(string name = "mem_sequence");
    super.new(name);
  endfunction
   
  virtual task body();
 
    req = mem_seq_item::type_id::create("req"); ///<------------------------------------------ Here he creates the req and puts in factory registry isn't it?
    wait_for_grant();
    req.randomize();
    send_request(req); 
    wait_for_item_done();
 
  endtask
   
endclass

then he seems to access it in driver class without even declaring its type?


class mem_driver extends uvm_driver #(mem_seq_item);
 
  // Virtual Interface
  virtual mem_if vif;
 
  `uvm_component_utils(mem_driver)
     
  //uvm_analysis_port #(mem_seq_item) Drvr2Sb_port;
 
  // Constructor
  function new (string name, uvm_component parent);
    super.new(name, parent);
  endfunction : new
 
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
     if(!uvm_config_db#(virtual mem_if)::get(this, "", "vif", vif))
       `uvm_fatal("NO_VIF",{"virtual interface must be set for: ",get_full_name(),".vif"});
  endfunction: build_phase
 
  // run phase
  virtual task run_phase(uvm_phase phase);
    forever begin
    seq_item_port.get_next_item(req);// <-------------------------------------------------------------how was he able to access the req without even declaring it.?
    //respond_to_transfer(req);
    drive();
    seq_item_port.item_done();
    end
  endtask : run_phase
 
  // drive 
  virtual task drive();
    req.print();
      `DRIV_IF.wr_en <= 0;
      `DRIV_IF.rd_en <= 0;
      @(posedge vif.DRIVER.clk);
      `DRIV_IF.addr <= req.addr;
    if(req.wr_en) begin
        `DRIV_IF.wr_en <= req.wr_en;
        `DRIV_IF.wdata <= req.wdata;
      //$display("\tADDR = %0h \tWDATA = %0h",req.addr,trans.wdata);
        @(posedge vif.DRIVER.clk);
      end
    if(req.rd_en) begin
        `DRIV_IF.rd_en <= req.rd_en;
        @(posedge vif.DRIVER.clk);
        `DRIV_IF.rd_en <= 0;
        @(posedge vif.DRIVER.clk);
        req.rdata = `DRIV_IF.rdata;
       // $display("\tADDR = %0h \tRDATA = %0h",trans.addr,`DRIV_IF.rdata);
      end
      $display("-----------------------------------------");
  endtask : drive
 
endclass : mem_driver

I know the factory has something to do with it.

Can someone help explain this?

In reply to haithamx15:

  1. The code didn’t declare “req” variable in both sequence and driver. You can check in uvm_sequence and uvm_driver base class, they already declare “REQ req” item. For example:

virtual class uvm_sequence #(type REQ = uvm_sequence_item,
                             type RSP = REQ) extends uvm_sequence_base;
  REQ                req;

That’s why you can use “req” variable without compiling error.

  1. You must connect seq_item_port of driver to seq_item_export of sequencer (usually implemented in agent). The sequencer will transfer the “req” from sequence to driver.

In reply to chris_le:

In addition to Chris_le, note this is OVM old style:

class mem_sequence extends uvm_sequence#(mem_seq_item);
  `uvm_sequence_utils(mem_sequence,mem_sequencer)

In the UVM it is simply

class mem_sequence extends uvm_sequence#(mem_seq_item);
  `uvm_object_utils(mem_sequence)