Вы находитесь на странице: 1из 19

UVM Questions and

Answers
Suman Halder
1) What are the three main types of UVM classes

UVM Classes

UVM consists of three main types of UVM classes,

    uvm_object
    uvm_transaction
    uvm_component

uvm_object
Core class based operational methods (create, copy, clone, compare, print, record, etc..), instance identification fields (name, type name,
unique id, etc.) and random seeding were defined in it.
    All uvm_transaction and uvm_component were derived from the uvm_object.

uvm_transaction

   Used in stimulus generation and analysis.

uvm_component
Components are quasi-static objects that exist throughout the simulation.
    Every uvm_component is uniquely addressable via a hierarchical path name, e.g. 'env.agent.driver'.
    The uvm_component also defines a phased test flow, that components follow during the course of the simulation. Each phase(build,
connect, run, etc.) is defined by a callback that is executed in precise order.
    The uvm_component also defines configuration, reporting, transaction recording, and factory interfaces.
2) Write a simple UVM code which will print values using print() method.
class mem_seq_item extends uvm_sequence_item;
  //Control Information
  rand bit [3:0] addr;
  rand bit       wr_en; //-------------------------------------------------------------------------
  rand bit       rd_en;
   //Simple TestBench to create and randomize sequence item
  //Payload Information //-------------------------------------------------------------------------
  rand bit [7:0] wdata;
  //Analysis Information module seq_item_tb;
       bit [7:0] rdata;   
   //::TODO:: comment the any of the `uvm_field_* macro and observe the
output of methods. i.e o/p of print(), copy(), compare() etc
  //instance
    //Utility and Field macros,   mem_seq_item seq_item;
  `uvm_object_utils_begin(mem_seq_item)   
    `uvm_field_int(addr,UVM_ALL_ON)
    `uvm_field_int(wr_en,UVM_ALL_ON)   initial begin
    `uvm_field_int(rd_en, 2UVM_ALL_ON)     //create method
    `uvm_field_int(wdata,UVM_ALL_ON)
  `uvm_object_utils_end     seq_item = mem_seq_item::type_id::create();
       
  //Constructor
  function new(string name = "mem_seq_item");
    //randomizing the seq_item
    super.new(name);     seq_item.randomize();
  endfunction     
  
  //constaint, to generate any one among write and read     //printing the seq_item
  constraint wr_rd_c { wr_en != rd_en; };     seq_item.print();  
  
endclass   end  
endmodule
3) Explain with example how clone() method works.

class mem_seq_item extends uvm_sequence_item;


  //data and control fields //-------------------------------------------------------------------------
  rand bit [3:0] addr; //Simple TestBench to access sequence item
  rand bit       wr_en; //-------------------------------------------------------------------------
  rand bit       rd_en;
module seq_item_tb;
  rand bit [7:0] wdata;
       bit [7:0] rdata;   
     //instance
  //Utility and Field macros,   mem_seq_item seq_item_0;
  `uvm_object_utils_begin(mem_seq_item)   mem_seq_item seq_item_1;
    `uvm_field_int(addr,UVM_ALL_ON)   
    `uvm_field_int(wr_en,UVM_ALL_ON)   initial begin
    `uvm_field_int(rd_en,UVM_ALL_ON)     //create method
    `uvm_field_int(wdata,UVM_ALL_ON)     seq_item_0 = mem_seq_item::type_id::create("seq_item_0");
  `uvm_object_utils_end
    
  
  //Constructor     seq_item_0.randomize(); //randomizing the seq_item  
  function new(string name = "mem_seq_item");     seq_item_0.print();     //printing the seq_item_0
    super.new(name);     
  endfunction     //clone method
       $cast(seq_item_1,seq_item_0.clone()); //create seq_item_1 and copy seq_item_0 to
  //constaint, to generate any one among write and read seq_item_1
  constraint wr_rd_c { wr_en != rd_en; };     
       //changing the seq_item_1 values will not reflect on seq_item_0 values.
endclass
    seq_item_1.addr  = 8;
    seq_item_1.wdata = 'h56;
    `uvm_info("","Printing seq_item_0", UVM_LOW)
    seq_item_0.print();          //printing the seq_item_0
    `uvm_info("","Printing seq_item_1", UVM_LOW)
    seq_item_1.print();          //printing the seq_item_1
    
    //Note:: name of seq_item_1 will be printed as seq_item_0, because there is no option to
pass argument to create method while calling the clone method.
  end  
endmodule
4) What is UVM sequence??What is the format of it??

A sequence generates a series of sequence_item's and sends it to the driver via sequencer, Sequence is written by extending the uvm_sequence.

A uvm_sequence is derived from an uvm_sequence_item


    a sequence is parameterized with the type of sequence_item, this defines the type of the item sequence that will send/receive to/from the driver.
sequence base class
virtual class uvm_sequence #( type REQ = uvm_sequence_item,
                               type RSP = REQ ) extends uvm_sequence_base

example:
class write_sequence extends uvm_sequence #(mem_seq_item);
....
....
endclass

the sequence has handle req and rsp of mem_seq_item.

request/req:
A transaction that provides information to initiate the processing of a particular operation.

response/rsp:
A transaction that provides information about the completion or status of a particular operation.
5) How UVM sequence is  executed ?? Explain briefly.

Most important properties of a sequence are,

    body method
    m_sequencer handle

body Method:
body method defines, what the sequence does.

m_sequencer Handle:
The m_sequencer handle contains the reference to the sequencer on which the sequence is running.

The sequence will get executed upon calling the start of the sequence from the test.

sequence_name.start(sequencer_name);

sequencer_name specifies on which sequencer sequence has to run.

    There are Methods, macros and pre-defined callbacks associated with uvm_sequence.
    Users can define the methods(task or function) to pre-defined callbacks. these methods will get executed
automatically upon calling the start of the sequence.
    These methods should not be called directly by the user.
Starting The Sequence:
Communication between the Sequence and driver involves below
Logic to generate and send the sequence_item will be written inside the body() method of the sequence. steps,
The handshake between the sequence, sequencer and driver to send the sequence_item is given below. 1.create_item() / create req.
2.wait_for_grant().
3.randomize the req.
4.send the req.
5.wait for item done.
6.get response.
Writing UVM Sequence

class mem_sequence extends uvm_sequence#(mem_seq_item);


  
  `uvm_object_utils(mem_sequence)
    
  //Constructor
  function new(string name = "mem_sequence");
    super.new(name);
  endfunction
  
  virtual task body();
 
    req = mem_seq_item::type_id::create("req");//create
the req (seq item)
    wait_for_grant();              //wait for grant
    assert(req.randomize());   //randomize the req    
             
    send_request(req);      //send req to driver
    wait_for_item_done();  //wait for item done from
driver
    get_response(rsp);    //get response from driver
 
  endtask
endclass
 
// assert(req.randomize());, will return the assertion
error on randomization failure.
6)Explain With Example functionality of UVM
sequence Macros.like
`uvm_do(),`uvm_create(),`uvm_send(),`uvm_rand_se
nd(),`uvm_do_with() and `uvm_rand_send_with()

`uvm_do() `uvm_create() and `uvm_send()


 This macro takes seq_item or sequence as argument.  `uvm_create(Item/Seq) :This macro creates the item or
On calling `uvm_do() the above-defined 6 steps will be sequence.
executed. `uvm_send(Item/Seq) :create() and randomize() are
skipped, rest all other steps are executed.
class mem_sequence extends
class mem_sequence extends uvm_sequence#(mem_seq_item);
uvm_sequence#(mem_seq_item);   
     `uvm_object_utils(mem_sequence)
  `uvm_object_utils(mem_sequence)     
       //Constructor
  //Constructor   function new(string name = "mem_sequence");
  function new(string name = "mem_sequence");     super.new(name);
    super.new(name);   endfunction
  
  endfunction   virtual task body();
       `uvm_create(req)
  virtual task body();     assert(req.randomize());
    `uvm_do(req)     `uvm_send(req);
  endtask   endtask
     
endclass
endclass
`uvm_rand_send()
`uvm_do_with()
Only create() is skipped, rest all other steps are
executed. This macro performs above 6 steps along
with constraints defined in second
class mem_sequence extends argument.
uvm_sequence#(mem_seq_item);
   class write_sequence extends
  `uvm_object_utils(mem_sequence) uvm_sequence#(mem_seq_item);
       
  //Constructor   `uvm_object_utils(write_sequence)
  function new(string name = "mem_sequence");     
    super.new(name);   //Constructor
  endfunction   function new(string name =
   "write_sequence");
  virtual task body();     super.new(name);
    `uvm_create(req)   endfunction
    `uvm_rand_send(req)   
  endtask   virtual task body();
       `uvm_do_with(req,{req.wr_en == 1;})
endclass   endtask
  
endclass
`uvm_rand_send_with()

create() is skipped, rest all other steps are executed along with constraints defined in second
argument.

class read_sequence extends uvm_sequence#(mem_seq_item);


  
  `uvm_object_utils(read_sequence)
    
  //Constructor
  function new(string name = "read_sequence");
    super.new(name);
  endfunction
  
  virtual task body();
    `uvm_create(req)
    `uvm_rand_send_with(req,{req.rd_en == 1;})
  endtask
  
endclass
7) What are the differences between m_sequencer and p_sequencer ??

m_sequencer,
The m_sequencer handle contains the reference to the sequencer(default
sequencer) on which the sequence is running.
This is determined by,

    the sequencer handle provided in the start method


    the sequencer used by the parent sequence
    the sequencer that was set using the set_sequencer method

p_sequencer,
The p_sequencer is a variable, used as a handle to access the sequencer
properties.
  p_sequencer is defined using the macro
`uvm_declare_p_sequencer(SEQUENCER_NAME)
8) What is UVM Sequencer ??

The sequencer controls the flow of request and response sequence items between sequences and the driver.
Sequencer and driver uses TLM Interface to communicate transactions.
uvm_sequencer and uvm_driver base classes have seq_item_export and seq_item_port defined respectively.
User needs to connect them using TLM connect method.
Example:
driver.seq_item_port.connect(sequencer.seq_item_export);
A sequencer can be written by extending the uvm_sequencer parameterized with the seq_item type.

UVM Sequencer Code

class mem_sequencer extends uvm_sequencer#(mem_seq_item);


 
   `uvm_sequencer_utils(mem_sequencer)
      
  function new (string name, uvm_component parent);
    super.new(name, parent);
  endfunction : new
 
endclass : mem_sequencer
9) What is UVM config DB?? How get() and set() methods works??Explain With example
UVM Config DB: The configuration database provides access to a centralized database, where type specific information can be stored and received. config_db can contain scalar objects, class handles,
queues, lists, or even virtual interfaces.The database has both a name table and a type table and each resource is entered into both. Resources are stored in a database so that each resource can be
retrieved by name or by type, and the database is globally accessible.
 uvm config db get and set

uvm_config_db::set and uvm_config_db::get methods are used to store and retrieve the information from the database respectively.
uvm config db set method
void uvm_config_db#(type T = int)::set(uvm_component cntxt, string inst_name, string field_name, T value);
Where,
 T  is the type of element being configured.
      Type can be scalar objects, class handles, queues, lists, or even virtual interfaces).
 cntxt is the hierarchical starting point of where the database entry is accessible.
inst_name is a hierarchical path that limits the accessibility of the database entry.
    example:
           top.env.agent.monitor
           top.*                       -  all of the scopes whose top-level component is top.
           top.env.*.monitor   -  all of the scopes in env that end in the monitor;
 field_name is the label used as a lookup for the database entry.
 value is the value to be stored in the database.

uvm_config_db set example


Below example shows, setting the interface handle intf, type mem_if, label mem_intf with global scope.

mem_if intf(clk,reset);  //interface instance


uvm_config_db#(virtual mem_if)::set(null,"*","mem_intf",intf);  //set method

 uvm config db get method


bit uvm_config_db#(type T=int)::get(uvm_component cntxt, string inst_name, string field_name, ref T value);

 value is the variable to which the value is to be retrieved from the database.
  * The other fields are the same as in set method.

The method returns 1 if it is successful and 0 if there is no such resource of this type in the database.

uvm_config_db get example

Below example shows. Using the get method to get a virtual interface handle from a database and assigns it to mem_vif. If the get method fails, the fatal message will be displayed.

virtual interface mem_if mem_vif;    //virtual interface declaration


if( !uvm_config_db#(virtual mem_if)::get(this,"*", "mem_intf", mem_vif))
  `uvm_fatal(get_full_name(),{"virtual interface must be set for:",".mem_vif"} ); //get method
11) What is UVM driver ?? What are the UVM drivers method??
A driver is written by extending the uvm_driver.

uvm_driver is inherited from uvm_component, Methods and TLM port


(seq_item_port) are defined for communication between sequencer and
driver.

The uvm_driver is a parameterized class and it is parameterized with the


type of the request sequence_item and the type of the response
sequence_item. 

UVM_Driver Methods

get_next_item
This method blocks until a REQ sequence_item is available in the sequencer.

try_next_item
This is a non-blocking variant of the get_next_item() method. It will return a
null pointer if there is no REQ sequence_item available in the sequencer.

item_done
The non-blocking item_done() method completes the driver-sequencer
handshake and it should be called after a get_next_item() or a successful
try_next_item() call.

put
The put() method is non-blocking and is used to place an RSP
sequence_item in the sequencer.
// run phase
  virtual task run_phase(uvm_phase phase);
    forever begin
    seq_item_port.get_next_item(req);
class mem_driver extends uvm_driver #(mem_seq_item);     //respond_to_transfer(req);
      drive();
  // Virtual Interface     seq_item_port.item_done();
  virtual mem_if vif;     end
    endtask : run_phase
 
  `uvm_component_utils(mem_driver)   // drive
        virtual task drive();
  //uvm_analysis_port #(mem_seq_item) Drvr2Sb_port;     req.print();
        `DRIV_IF.wr_en <= 0;
  // Constructor       `DRIV_IF.rd_en <= 0;
  function new (string name, uvm_component parent);       @(posedge vif.DRIVER.clk);
    super.new(name, parent);       `DRIV_IF.addr <= req.addr;
  endfunction : new     if(req.wr_en) begin
`         `DRIV_IF.wr_en <= req.wr_en;
 
        `DRIV_IF.wdata <= req.wdata;
  function void build_phase(uvm_phase phase);       //$display("\tADDR = %0h \tWDATA = %0h",req.addr,trans.wdata);
 
    super.build_phase(phase);         @(posedge vif.DRIVER.clk);
     if(!       end
uvm_config_db#(virtual mem_if)::get(this, "", "vif", vif))     if(req.rd_en) begin
       `uvm_fatal("NO_VIF",{"virtual interface must be set for:         `DRIV_IF.rd_en <= req.rd_en;
",get_full_name(),".vif"});         @(posedge vif.DRIVER.clk);
  endfunction: build_phase         `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
12) What is UVM
class mem_monitor extends uvm_monitor;
monitor??  
  // Virtual Interface
The user-defined monitor is extended from   virtual mem_if vif;
uvm_monitor, uvm_monitor is inherited by  
uvm_component.
  uvm_analysis_port #(mem_seq_item) item_collected_port;
A monitor is a passive entity that samples the DUT  
signals through the virtual interface and converts the   // Placeholder to capture transaction information.
signal level activity to the transaction level.
  mem_seq_item trans_collected;
Monitor samples DUT signals but does not drive  
them.   `uvm_component_utils(mem_monitor)
The monitor should have an analysis port (TLM port)
 
and a virtual interface handle that points to DUT   // new - constructor
signals   function new (string name, uvm_component parent);
    super.new(name, parent);
    trans_collected = new();
    item_collected_port = new("item_collected_port", this);
  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("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"});
  endfunction: build_phase
 
  // run phase
  virtual task run_phase(uvm_phase phase);
    item_collected_port.write(trans_collected);
  endtask : run_phase
 
endclass : mem_monitor
13) What is UVM Agent ?? What is Active agent and Passive
Agent??
a user-defined agent is extended from uvm_agent, uvm_agent is class mem_agent extends uvm_agent;
inherited by uvm_component.   //declaring agent components
  mem_driver    driver;
An agent typically contains a driver, a sequencer, and a monitor.   mem_sequencer sequencer;
  mem_monitor   monitor;
Agents can be configured either active or passive.   
 Active agent:    // UVM automation macros for general components
  `uvm_component_utils(mem_agent)
 
Active agents generate stimulus and drive to DUT.   // constructor
  function new (string name, uvm_component parent);
An active agent shall consists of all the three components driver,     super.new(name, parent);
sequencer, and monitor.   endfunction : new
 
 Passive agent:    // build_phase
  function void build_phase(uvm_phase phase);
Passive agents sample DUT signals but do not drive them.     super.build_phase(phase);
 
A passive agent consists of only the monitor.     if(get_is_active() == UVM_ACTIVE) begin
      driver = mem_driver::type_id::create("driver", this);
 get_is_active() Method:        sequencer = mem_sequencer::type_id::create("sequencer", this);
    end
 
get_is_active() Returns UVM_ACTIVE if the agent is acting as an active     monitor = mem_monitor::type_id::create("monitor", this);
agent and UVM_PASSIVE if the agent acting as a passive agent   endfunction : build_phase
 
  // connect_phase
  function void connect_phase(uvm_phase phase);
    if(get_is_active() == UVM_ACTIVE) begin
      driver.seq_item_port.connect(sequencer.seq_item_export);
    end
  endfunction : connect_phase
 
endclass : mem_agent
14) What is the purpose of class mem_scoreboard extends uvm_scoreboard;
UVM scoreboard?? How it  
  `uvm_component_utils(mem_scoreboard)
can be use in code??   uvm_analysis_imp#(mem_seq_item, mem_scoreboard) item_collec
The user-defined scoreboard is extended from uvm_scoreboard, ted_export;
uvm_scoreboard is inherited by uvm_component.  
the scoreboard will check the correctness of the DUT by comparing
the DUT output with the expected values.    // new - constructor
the scoreboard will receive the transactions from the Monitors   function new (string name, uvm_component parent);
implemented inside agents.     super.new(name, parent);
Monitor and scoreboard will communicate via TLM ports and exports.   endfunction : new
Scoreboard shall compare the DUT output values with,
 
  function void build_phase(uvm_phase phase);
The golden reference values.
    super.build_phase(phase);
The values Generated from the reference model.     item_collected_export = new("item_collected_export", this);
  endfunction: build_phase
   
  // write
  virtual function void write(mem_seq_item pkt);
    $display("SCB:: Pkt recived");
    pkt.print();
  endfunction : write
 
endclass : mem_scoreboard

Вам также может понравиться