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.