Hi,
I read the blog post on UVM Driver models and am trying to implement a driver for the case (simplified) below.
On the interface, there is an address channel & a Data channel.
On the address bus, four addresses are sent back to back.
After 4 address requests are placed, at the end of A4 Data bytes are placed on the data bus in succession
A1 A2 A3 A4
xx xx xx xx D1 D2 D3 D4
To realize this I used fork_join none blocks in the run_phase of the driver which has three threads running.
- Thread 1 will collect sequence items from the sequence and pushes them on a two queues
- Thread 2 drives address on VIF from one queue
- Thread 3 drives data from another queue after 3 cycles delay.
When simulated I see simulation terminates abruptly with no clear message ( on edaplayground). Could someone point the flaw in my implementation?
UVM_INFO dut_parallel_driver.sv(45) @ 3: uvm_test_top.env.agent.driver [t_driver] Outof Reset
./run.sh: line 8: 608 Killed ./simv +vcs+lic+wait ‘+UVM_TESTNAME=uvmtest’ ‘+UVM_VERBOSITY=UVM_MEDIUM’
Exit code expected: 0, received: 1
class t_driver extends uvm_driver #(packet);
`uvm_component_utils(t_driver)
virtual p_intf.tb_mp vif_tb;
packet pa[$];
packet pd[$];
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!(uvm_config_db #(virtual p_intf.tb_mp)::get(this,"","virtual_intf", vif_tb))) begin
`uvm_error(this.get_full_name,"Virtual Interface not set from agent");
end
endfunction
virtual task run_phase(uvm_phase phase);
packet req;
if(vif_tb.reset)
begin
`uvm_info(get_type_name(),$sformatf("Inside DUT Reset"),UVM_LOW);
vif_tb.cb.valid <= 0;
wait(!vif_tb.reset);
end
forever
begin
fork
begin
seq_item_port.get_next_item(req);
`uvm_info(get_type_name(),$sformatf("Fetching next request"),UVM_LOW);
pa.push_back(req);
pd.push_back(req);
seq_item_port.item_done(req);
end
drive_address(pa);
drive_data(pd);
join_none
end
endtask
virtual task automatic drive_address(packet req[$]);
packet pkt_ad;
//wait until there are packets in Queue
while (req.size() == 0)
begin
@(vif_tb.cb);
end
`uvm_info(get_type_name(),$sformatf("Addr Queue Size = %0x", req.size()),UVM_LOW);
while (req.size()!=0)
begin
pkt_ad = req.pop_front();
`uvm_info(get_type_name(),$sformatf("Executing Addr = %0x", pkt_ad.addr),UVM_LOW);
vif_tb.cb.addr <= pkt_ad.addr;
vif_tb.cb.valid <= 1'b1;
@(vif_tb.cb);
vif_tb.cb.valid <= 1'b0;
end
endtask
virtual task automatic drive_data(packet req_d[$]);
packet pkt_dat;
//wait until there are packets in Queue
while (req_d.size() == 0)
begin
@(vif_tb.cb);
end
`uvm_info(get_type_name(),$sformatf("Data Queue Size = %0x", req_d.size()),UVM_LOW);
while(req_d.size()!=0)
begin
pkt_dat = req_d.pop_front();
`uvm_info(get_type_name(),$sformatf("Executing Data = %0x", pkt_dat.data),UVM_LOW);
repeat(3) @(vif_tb.cb);
vif_tb.cb.data <= pkt_dat.data;
end
endtask
endclass