driver怎么将response返回给sequence

driver返回sequence response有三种方式:

driver将数据包下发dut后,先构造一个rsp,再获取req的id信息,最后将rsp反馈给sequence

1. 通过seq_item_port.item_done(rsp)返回response。当存在多个response时,将response作为item_done参数的方式就不适用了,由于一个transaction只能对应一个item_done,所以使用多次item_done(rsp)是会出错的 

while(1) begin
  seq_item_port.get_next_item(req);
  drive_one_pkt(req);
  rsp = new("rsp");            //
  rsp.set_id_info(req);        //
  seq_item_port.item_done(rsp);//
end

2. driver也可以通过put_response(rsp)函数或put(rsp)函数,put_response()是一个blocking方法,所以sequence必须有一个对应的get_response(rsp)

3. 使用uvm_driver的内置analysis port, rsp_port.write(rsp);

为了保证request_item和response_item两个对象的独立性,建议使用clone()的方式单独创建response_item。

sequence_item的ID赋值:

sequence_item的ID没有经过域的自动化声明,在克隆时只会复制数据而不会复制id,所以在提供response之前,必须将response transaction与request transaction通过id号相对应,有两种方法:

1. 通过rsp.set_id_info(req)方法,将引用项(req)中的序列号(sequence_id)和事务号(transaction_id)复制到调用项(rsp)中

2. 通过rsp.set_sequence_id( req.get_sequence_id() )方法,获取req中的序列号给rsp打上id号

response机制:

原理是driver将rsp推送给sequencer,而sequencer内部维持一个队列,当有新的response进入时,就推入此队列。但是此队列的大小并不是无限制的,默认情况下,其大小为8,当队列中有8个response时,如果driver再次向此队列推送新的response,UVM就会给出如下错误提示:

UVM_ERROR@1753500000:uvm_test_top.env.i_agt.sqr@@case0_sequence[uvm_test_top.env.i_agt.sqr.case0_sequence] Response queue overflow, response was dropped 

因此,如果在driver中每个transaction后都发送一个response,而sequence又没能及时get_response,sequencer中的response队列就存在溢出的风险

另类的response:

1. 使用response handler功能

前面讲述的get_response和put_response是一一对应的。当在sequence中启动get_response时,进程就会阻塞在那里,一直到response_queue中被放入新的记录。如果driver能够马上将response通过put_response的方式传回sequence,那么sequence被阻塞的进程就会得到释放,可以接着发送下一个transaction给driver。但是假如driver需要延时较长的一段时间才能将transaction传回,在此期间,driver希望能够继续从sequence得到新的transaction并驱动它,但是由于sequence被阻塞在了那里,根本不可能发出新的transaction。

发生上述情况的主要原因为sequence中发送transaction与get_response是在同一个进程中执行的,假如将二者分离开来,在不同的进程中运行将会得到不同的结果。在这种情况下需要使用response_handler:

//my_case0.sv
3 class case0_sequence extends uvm_sequence #(my_transaction);
…
10   virtual task pre_body();
11     use_response_handler(1);  //打开response的response_handler功能
12   endtask
13
14   virtual function void response_handler(uvm_sequence_item response);  //当打开response_handler功能后,用户需要
15     if(!$cast(rsp, response))   //重载虚函数response_handler。此函数的参数是一个uvm_sequence_item类型的指针,需要                                         
16       `uvm_error("seq", "can't cast")//首先将其通过cast转换为my_transactiono类型,之后就可以根据rsp的值来决定后续
17     else begin                       //sequence的行为。
18       `uvm_info("seq", "get one response", UVM_MEDIUM)
19       rsp.print();
20     end
21   endfunction                                                          
22
23   virtual task body();
24     if(starting_phase != null)
25       starting_phase.raise_objection(this);
26     repeat (10) begin
27       `uvm_do(m_trans)
28     end
29     #100;
30     if(starting_phase != null)
31       starting_phase.drop_objection(this);
32   endtask
33
34   `uvm_object_utils(case0_sequence)
35 endclass

由于response handler功能默认是关闭的,所以要使用response_handler,首先需要调用use_response_handler函数,打开sequence的response handler功能。当打开response handler功能后,用户需要重载虚函数response_handler。此函数的参数是一个uvm_sequence_item类型的指针,需要首先将其通过cast转换变成my_transaction类型,之后就可以根据rsp的值来决定后续sequence的行为

要注意一旦采用response_handler机制后,在当前sequence里一定不能用get_response,它会get不到response,一直block住。如果transaction_id不为-1,get_response会在response_queue里检索,直到找到1个匹配对应transaction_id的response为止

2. 使用原transaction

无论是put/get_response或者response_handler,都是新建了一个transaction,并将其返回给sequence。事实上,当一个uvm_do语句执行完毕后,其第一个参数并不是一个空指针,而是指向刚刚被送给driver的transaction。利用这一点,可以实现一种另类的response:

//my_driver.sv
22 task my_driver::main_phase(uvm_phase phase);
…
27   while(1) begin
28     seq_item_port.get_next_item(req);
29     drive_one_pkt(req);
30     req.frm_drv = "this is information from driver";  //
31     seq_item_port.item_done();
32   end
33 endtask

driver中向req中的成员变量赋值,而sequence则检测这个值:

//my_case0.sv
3 class case0_sequence extends uvm_sequence #(my_transaction);
…
10   virtual task body();
…
13     repeat (10) begin
14       `uvm_do(m_trans)
15       `uvm_info("seq", $sformatf("get information from driver: %0s", m_trans.frm_drv), UVM_MEDIUM)  //
16     end
…
20   endtask
21
22   `uvm_object_utils(case0_sequence)
23 endclass
其他
  • 关于本文,您有什么想法均可在评论区留言交流。
  • 自身能力不足,如有错误还请多多指出!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

uvm_1.2

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值