| ||
UVM为同步sequence, sequencer, driver,提供了强大的握手机制,其中put/get response是为了让driver将transaction发送给DUT后,告诉sequence该笔transaction发送完成。normal的使用方法是在sequence产生transaction,并将其send给driver后执行get_response操作,由于get_response是blocking的,因sequence会一直等到driver执行put_response;driver接收到sequence发来的transaction后,对该transaction进行处理(如:send to dut), 处理完成后,通过put_response告诉sequence该笔transaction处理完成。下图给出sequence, sequencer与driver的握手机制。
从上图可以看出driver执行put response, 而sequence执行get response,并且put response是非阻塞的,而get_response是阻塞的,这样就保证了sequence, sequencer与driver之间的handshake。
以上介绍了put/get_response最基本的功能,下面介绍一下UVM中response的实现。UVM中的get_response在uvm_sequence.svh中定义,以下是get_response函数的原型,通常我们不会care transaction_id, 并且uvm_sequence.svh中定义了RSP类型的rsp, 因此我们在sequence中get_response(rsp)即可。
virtual task get_response(output RSP response, input int transaction_id = -1);
uvm_sequence_item rsp;
get_base_response( rsp, transaction_id);
$cast(response,rsp);
endtask
response的使用中经常会看到log中显示response_queue overflows,那么这是什么原因的导致的呢?通过查找UVM的库不难发现,在uvm_sequence_base.svh中定义了以下几个function:
function void set_response_queue_error_report_disabled(bit value);
response_queue_error_report_disabled = value;
endfunction
function bit get_response_queue_error_report_disabled();
return response_queue_error_report_disabled;
endfunction
function void set_response_queue_depth(int value);
response_queue_depth = value;
endfunction
function int get_response_queue_depth();
return response_queue_depth;
endfunction
virtual function void clear_response_queue();
response_queue.delete();
endfunction
从以上5个function可看出UVM中response的机制,首先 是定义一个queue,用于存放response,protected uvm_sequence_item response_queue[$]; 并定义一该queue的深度,protected int response_queue_depth = 8; 由此可见有一个depth为8的queue用于存放response,每当put_response时,就向该queue中放sequence_item,当get_response时,从queue中取出sequence_item。
另外,put_response的操作通常在driver中完成,但是却在uvm_sequence_base.svh中找到了put_response函数的实现,其通过调用put_base_response向response_queue中写数据,并且,当response_queue满时,再调用put_response函数时,就会出现Response queue overflow的error。
virtual function void put_base_response(input uvm_sequence_item response);
if ((response_queue_depth == -1) || (response_queue.size() < response_queue_depth)) begin
response_queue.push_back(response);
return;
end
if (response_queue_error_report_disabled == 0) begin
uvm_report_error(get_full_name(), "Response queue overflow, response was dropped", UVM_NONE);
end
endfunction
virtual function void put_response (uvm_sequence_item response_item);
put_base_response(response_item); // no error-checking
endfunction