接着上次的参数化 agent,我们接着介绍driver部分。【UVM 参数化的VIP】- Agent_dajiao_zi的博客-CSDN博客
还是一样,我们直接看代码:
class comm_driver `COMM_PARAM_DECL extends uvm_driver#(comm_seq_item);
`uvm_component_param_utils(comm_driver `COMM_PARAM_INST)
//function new
//build phase
task run_phase(uvm_phase phase)
super.run_phase(phase);
forever begin
wait_for_reset();
do_reset();
fork
do_drive_req();
do_drive_resp();
wait_for_reset();
join_any
disable fork;
end
endtask
endclass
这部分比较单纯,就是在run_phase中调用两个chanel(req和resp)的drive函数,其中有必要提一下的是wait_for_reset()函数,这个是为了支持动态reset,一旦monitor到reset有效,就会立即disable掉driver,然后开启下一轮循环。
task do_drive_req();
SEQ_ITEM _tr;
forever begin
seq_item_port.get_next_item(req);
if(!cast(_tr,req.clone())) `uvm_fatal(get_full_name(),"req cast error")
_tr.set_id_info(req);
_tr.field_assign();//for user to fill
//logic for req channel
//delay logic to assert req_valid etc.
m_resp_pend_q.push_back(_tr);
seq_item_port.item_done();
end
endtask
SEQ_ITEM来自agent的参数输入,field_assign函数用来 方便user定义自己的seq_item里面各个field的含义,比如对于address的低4bits,对user1来说是offset的含义,对user2来说低3bits才是offset的含义,就可以通过这个函数来区分。
task do_drive_resp();
SEQ_ITEM _tr;
RESP_ITEM _resp;
forever begin
wait(vif.resp_valid==1);
//delay logic and driver resp_ready
//monitor resp channel info and check
_tr = m_resp_pend_q[i];
m_resp_pend_q.delete(i);
_resp.field_assign();
_tr.m_resp = _resp;
put_response(_tr);
end
endtask
类似,resp channel也提供一个field_assign函数给user。
好了,就到这边,slave driver类似,没啥特殊的,就不介绍了。