In reply to Digesh:
The uvm_driver class is just
class uvm_driver #(type REQ=uvm_sequence_item,
type RSP=REQ) extends uvm_component;
uvm_seq_item_pull_port #(REQ, RSP) seq_item_port;
uvm_analysis_port #(RSP) rsp_port;
REQ req;
RSP rsp;
function new (string name, uvm_component parent);
super.new(name, parent);
seq_item_port = new("seq_item_port", this);
rsp_port = new("rsp_port", this);
endfunction
const static string type_name = "uvm_driver #(REQ,RSP)";
virtual function string get_type_name ();
return type_name;
endfunction
endclass
Let say you want to create a different kind of driver with two different seq_item_pull ports and no response port.
class my_driver extends uvm_component;
`uvm_component_utils(my_driver)
uvm_seq_item_pull_port #(my_req_type1, my_rsp_type1) seq_item1_port;
uvm_seq_item_pull_port #(my_req_type2, my_rsp_type2) seq_item2_port;
my_req_type1 req1;
my_req_type2 req2;
my_rsp_type1 rsp1;
my_rsp_type2 rsp2;
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
seq_item1_port = new("seq_item1_port", this);
seq_item2_port = new("seq_item2_port", this);
...
endfunction
task run_phase(uvm_phase phase);
fork
forever send1; // tasks that would get their respective items from each sequencer
forever send2;
join
endtask
endclass
You could do something similar a monitor or coverage collector, etc. The key is the component is written with specific transaction classes in mind.