UVM callbacks

Hi,

could someone help me out in understanding below mentioned callback scenarios:
1.Drop a transaction using callbacks.
2.How the callbacks will be used in collecting coverage data.

It would be helpful is there is a example code.Thanks

Rgds,
Sudharshan

In reply to sudharshan:

I thibk you do not need callbacks for both scenarios.
In the driver or monitor you can simply drop a transaction by throwing it away.
Coverage collectors do not need a callback at all. It is simply evaluating your transacion data for your coverage model.

In reply to chr_sue:

Hi chr_sue,

Thanks for the response.
I read that instead of Callback go for OOP. But i just want to know how to drop a particular packet in the driver class using both OOP and Callback.
could you please post me a code so that it would be helpful

Rgds,
Suhdarshan

In reply to sudharshan:

Dropping data packets and functional coverage have nothing to do with callbacks.
Could you please tell me where you have read this?


// I hope it helps. put it all in a file and run it.
package tb_env;
  import uvm_pkg::*;
  `include "uvm_macros.svh"
  
  // Basic sequence item
  class shift_reg_item extends uvm_sequence_item;
    rand bit [7:0] data;
    rand bit [2:0] shift;
    
    `uvm_object_utils_begin(shift_reg_item)
    `uvm_field_int(data, UVM_ALL_ON)
    `uvm_field_int(shift, UVM_ALL_ON)
    `uvm_object_utils_end
    
    function new (string name="shift_reg_item");
      super.new(name);
    endfunction
    
  endclass
  
  // Basic sequence
  class shift_reg_seq extends uvm_sequence #(shift_reg_item);
    `uvm_object_utils(shift_reg_seq)
    
    shift_reg_item req;
    
    function new(string name="shift_req_seq");
      super.new(name);
    endfunction
    
    task body();
      req=shift_reg_item::type_id::create("req");
      start_item(req);
      if(!req.randomize())
      `uvm_fatal("shift_reg_seq","Failed to randomize shift_reg item")
      finish_item(req);
      // `uvm_do(req)
      // `uvm_do_with(req, {req.data==8'hAA; req.shift==3'b101;})
    endtask
  endclass
  
  // Sequencer
  class shift_reg_sqr extends uvm_sequencer #(shift_reg_item);
    
    `uvm_component_utils(shift_reg_sqr)
    
    function new (string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    
  endclass
  
  typedef class shift_reg_drv;
  
  // Callback parent class
  // here you define the method that will change the sequence
  // Implementation will be done in child class
  class driver_cb extends uvm_callback;
    `uvm_object_utils (driver_cb)
    
    function new (string name = "driver_cb");
      super.new(name);
    endfunction
    
    virtual function void set_seq_item_value (shift_reg_drv drv, shift_reg_item item);
    endfunction : set_seq_item_value
    
  endclass : driver_cb
  
  // Driver 
  class shift_reg_drv extends uvm_driver #(shift_reg_item);
    `uvm_component_utils(shift_reg_drv)

    // Register the callback class with this  driver class
    `uvm_register_cb (shift_reg_drv, driver_cb)
    
    function new (string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    
    // If the callback is added to this driver, this method
    // will call the method defined in the callback class (child callback class)
    virtual function void set_seq_item_value (shift_reg_item item);
      `uvm_do_callbacks(shift_reg_drv, driver_cb, set_seq_item_value(this, item))
    endfunction : set_seq_item_value
    
    task run_phase (uvm_phase phase);
      forever begin
        seq_item_port.get_next_item(req);
        // Call the callback method
        set_seq_item_value(req);
        req.print();
        seq_item_port.item_done();
      end
    endtask
  endclass
  
  // This class set data bit to ones
  // You can have many of this classes, each can do something else
  // make sure that they are all extend driver cb
  class set_seq_item_all_ones_cb extends driver_cb;
    `uvm_object_utils(set_seq_item_all_ones_cb)
    
    function new (string name = "set_seq_item_all_ones_cb");
      super.new(name);
    endfunction
    
    // Override the the method that was declared in driver_cb
    virtual function void set_seq_item_value (shift_reg_drv drv, shift_reg_item item);
      item.data = 8'hFF;
      item.shift = 3'h3;
    endfunction : set_seq_item_value
    
  endclass : set_seq_item_all_ones_cb
  
  class shift_reg_test extends uvm_test;
    
    shift_reg_seq seq;
    shift_reg_drv drv;
    shift_reg_sqr sqr;
    set_seq_item_all_ones_cb cb;
    
    `uvm_component_utils(shift_reg_test)
    
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    
    function void build_phase (uvm_phase phase);
      super.build_phase(phase);
      sqr=shift_reg_sqr::type_id::create("sqr", this);
      drv=shift_reg_drv::type_id::create("drv", this);
      seq=shift_reg_seq::type_id::create("seq");
      cb=set_seq_item_all_ones_cb::type_id::create("cb");
    endfunction
    
    function void connect_phase (uvm_phase phase);
      super.connect_phase(phase);
      drv.seq_item_port.connect(sqr.seq_item_export);
    endfunction
    
    task run_phase (uvm_phase phase);
      super.run_phase(phase);
      phase.raise_objection(this);
      // Start sequence with out callback
      seq.start(sqr);
      // Here is where you add the callback functionality to the driver
      // if you want to change is behaviour
      uvm_callbacks #(shift_reg_drv, driver_cb)::add(drv, cb);
      // Start the sequence with add callback functionality to the driver
      seq.start(sqr);
      // If you want you can remove to callback functionality fro the driver
      uvm_callbacks #(shift_reg_drv, driver_cb)::delete(drv, cb);
      // Start sequence without callback
      seq.start(sqr);
      phase.drop_objection(this);
    endtask
    
  endclass
endpackage : tb_env

module top;
  import uvm_pkg::*;
  `include "uvm_macros.svh"
  import tb_env::*;
  
  initial run_test("shift_reg_test");
endmodule



In reply to shimonc:

I see what are you doing, but I do not really understand the value or benefit of this callback. You can do the same without the callback. Looks like Synopsys style.

Of course you can write a callback for discarding certain transactions. But you can do this also in another way.

Agree, I never used callbacks.
I usually extend classes and change there behavior.
But sudharshan wanted to see an example so I gave one.

In reply to shimonc:

OK, I understand.
I see the callback as an add-on and not as an alternative.
The callback allows us to make modifications without extending a class.

In reply to shimonc:

Thank you for the complete code
I have read in some reference document

One more clarification :
If I want to drop a packet in the driver class do I need to call item done twice ?
Example : I have generated 5 packets and I need to drop 3 and 5 packet in the driver class .is it possible?
Please let me know.

Kind Regards,
Sudharshan

In reply to sudharshan:

get_naxt_item and seq_itrm_done has to be called as a pair.
You need an indication which sseq_items to drop, i.e. the number of the item or any other indication. In this case you are callingget_next_item()
and immediately after this item_done. This will drop this seq_item.