1.与sequencer之间完成握手。
当 driver 使用 get_next_item( ) 得到一个 transaction 时,sequencer 同时也会保留一份这个刚刚发送出去的 transaction。当 driver 没有得到 transaction 的情况下,sequencer会将这个 transaction 重新再发送一遍给driver。
那么 sequencer 如何得知 driver 没有收到这个 transaction 呢?
- 就是通过 item_done 的方式告诉 sequencer。当driver 再次调用 get_next_item 获取下一个 transaction 时,如果此时 sesequencer 知道 driver 调用了 item_done,那么 sequencer 就认为上一次事务 driver 接受到了。
- 反之,如果 driver 再次调用 get_next_item时,sequencer 发现上一次的 item_done 没有被调用,则 sequencer 认为 driver 没有接收到,会将保留的 transaction 再发送一遍。
2.与sequence之间完成握手。
当 sequence 中的调用宏 uvm_do 等创建事务时,它并不会立即返回执行下一次 uvm_do,而是等待 driver 返回 item_done 信号之后,此时,uvm_do 才算执行完毕,返回后执行下一次 uvm_do,产生新的 transaction。
当然,我们拆解宏 uvm_do。当我们调用宏时,在sequence的body( )任务中产生 transaction 的步骤如下:
- 创建 item :调用 create_item( bus_trans::get_type() , m_sequencer , “rsp” )函数,返回一个uvm_sequence_item类型的对象;
- 发送 item :调用 start_item( ) 函数,等待获取 sequencer 的授权许可(注:这里涉及到 sequencer 的仲裁,文末有解释),由于是函数,会立即返回结果;
- 随机化 item :在获取到 sequencer 的授权后,对 item 做随机化;
- 完成发送 item :随机化后,调用finish_item( )任务。但这是一个阻塞的任务,不会立即执行结束。需要等待 driver 的 item_done() 返回,才执行结束,完成握手;
class transaction extends uvm_sequence_item;
rand int data;
`uvm_object_utils_begin(transaction)
`uvm_field_int(data,UVM_ALL_ON)
`uvm_object_utils_end
endclass
class my_sequence extends uvm_sequence;
`uvm_object_utils(my_sequence)
...
task body();
uvm_sequence_item item;
transaction req rsp;
item = create_item(transaction::get_type(),m_sequencer,"req");
void'($cast(req,item));
start_item(req);
req.randomize with{data == 1;}
finish_item();
endtask
endclass
总结
不难看出,item_done 完成了与 sequencer 和 sequence 之间的握手,以此提高了数据传输的可靠性。
- 第一,与 sequencer 之间的握手,防止数据传输出错而丢包;
- 第二,与 sequence 之间完成握手,告诉 sequence 可以结束上一次的 transaction ,开始产生下一个新事务。
PS:sequencer 的仲裁机制
这里还是想补充一下关于 sequencer 的仲裁机制,方便阅读。如下:
sequence 在向 sequencer 发送 transaction 之前,需要先向 sequencer 发送一个请求,sequencer 把这个请求放在一个仲裁队列中。
- 如果仲裁队列中有发送请求,但是 driver 没有申请 transaction,那么 sequencer 将会一直处于等待 driver 的状态,直到 driver 申请新的transaction。此时,sequencer 同意 sequence 的发送请求,sequence 在得到 sequencer 的批准后,产生一个 transaction 并交给 sequencer,sequencer 把这个 transaction 交给 driver。
- 如果仲裁队列中没有请求,但是 driver 向 sequencer 申请一个新的 transaction,那么 sequencer 将会处于等待sequence 的状态,一直到有 sequence 递交申请。此时,sequencer会马上同意这个请求,sequence 产生 transaction 并交给 sequencer,最终 driver 获得这个 transaction 。