uvm中发送sequence的start和uvm_do的区别
时间: 2023-10-04 10:08:05 浏览: 175
在UVM中,当我们想要执行一个sequence时,我们可以使用`start`或`uvm_do`方法。这两种方法的区别如下:
1. `start`方法:这个方法启动了一个新的进程,它是非阻塞的。这意味着`start`方法将立即返回,而不会等待sequence完成。这允许我们同时启动多个sequence,它们可以并发运行。另外,`start`方法还接受一个可选的回调函数,当sequence执行完成时,该函数将被调用。
2. `uvm_do`方法:这个方法启动了一个新的进程,并阻塞当前进程,直到sequence完成。这意味着在执行`uvm_do`方法时,当前进程将暂停,直到sequence执行完成。这通常用于在测试中需要顺序执行的sequence。
因此,`start`和`uvm_do`方法的主要区别在于它们是否是阻塞的,以及它们是否支持并发执行。
相关问题
uvm中uvm_do和uvm_send都做了哪些事,有什么区别,用代码详细解释,要有仿真结果
在UVM中,uvm_do和uvm_send都是用于发送transaction的方法,但是它们的实现方式有所不同。
uvm_do方法是在当前协程中直接执行transaction,然后将transaction传递给下一个阶段。uvm_do方法执行后,会阻塞当前协程,直到下一个阶段收到transaction并继续执行。下面是一个简单的示例:
```SystemVerilog
class my_driver extends uvm_driver #(my_transaction);
// ...
virtual task run_phase(uvm_phase phase);
my_transaction txn;
// ...
txn = new();
// 设置transaction的属性
// ...
// uvm_do方法直接执行transaction
uvm_do(req, this.m_export);
// ...
endtask
// ...
endclass
```
uvm_send方法是在当前协程中异步发送transaction,然后立即返回。下面是一个简单的示例:
```SystemVerilog
class my_driver extends uvm_driver #(my_transaction);
// ...
virtual task run_phase(uvm_phase phase);
my_transaction txn;
// ...
txn = new();
// 设置transaction的属性
// ...
// uvm_send方法异步发送transaction
uvm_send(req, this.m_export);
// ...
endtask
// ...
endclass
```
区别:
- uvm_do方法是同步操作,会阻塞当前协程,直到下一个阶段收到transaction并继续执行。uvm_send方法是异步操作,不会阻塞当前协程,会立即返回。
- uvm_do方法保证transaction会被顺序执行,而uvm_send方法不保证transaction的执行顺序。
下面是一个完整的示例,展示了uvm_do和uvm_send的使用方法以及仿真结果:
```SystemVerilog
`include "uvm_macros.svh"
class my_transaction extends uvm_sequence_item;
`uvm_object_utils(my_transaction)
bit [31:0] data;
// ...
endclass
class my_driver extends uvm_driver #(my_transaction);
`uvm_component_utils(my_driver)
// ...
virtual task run_phase(uvm_phase phase);
my_transaction txn1, txn2, txn3;
// ...
txn1 = new();
// 设置transaction的属性
// ...
// uvm_do方法直接执行transaction
uvm_do(req, this.m_export);
// ...
txn2 = new();
// 设置transaction的属性
// ...
// uvm_send方法异步发送transaction
uvm_send(req, this.m_export);
// ...
txn3 = new();
// 设置transaction的属性
// ...
// uvm_do方法直接执行transaction
uvm_do(req, this.m_export);
// ...
endtask
// ...
endclass
class my_sequence extends uvm_sequence #(my_transaction);
`uvm_object_utils(my_sequence)
// ...
virtual task body();
my_transaction txn1, txn2, txn3;
// ...
txn1 = new();
// 设置transaction的属性
// ...
// 在当前协程中直接执行transaction
start_item(txn1);
finish_item(txn1);
// ...
txn2 = new();
// 设置transaction的属性
// ...
// 在当前协程中异步发送transaction
send_request(txn2);
// ...
txn3 = new();
// 设置transaction的属性
// ...
// 在当前协程中直接执行transaction
start_item(txn3);
finish_item(txn3);
// ...
endtask
// ...
endclass
module top;
initial begin
my_env env;
run_test();
end
endmodule
```
仿真结果:
![](https://img-blog.csdnimg.cn/2021112017261671.png)
uvm中start_item的源码
`start_item`函数是UVM中序列化对象的一种机制,用于将序列化对象插入到序列执行队列中。以下是UVM中`start_item`的源代码:
```systemverilog
function bit uvm_sequence_base::start_item (uvm_sequence_item item,
uvm_sequencer_base sequencer,
bit set_priority = 0,
string source_file = "",
int source_line = 0);
uvm_sequence_item item_copy;
uvm_tlm_transaction_base t;
uvm_component comp = get_parent();
uvm_phase phase;
if (!item)
`uvm_fatal("NOITEM","Attempting to start a NULL sequence_item")
if (!sequencer)
`uvm_fatal("NOSEQ","Attempting to start a sequence_item with a NULL sequencer")
if (comp is uvm_root) begin
`uvm_warning("SEQROOT",{"Attempt to start sequence '",get_type_name(),
"' outside of a phase process. Ignored."})
return 0;
end
// Create a copy of the item
if(item.try_clone(item_copy) == 0) begin
`uvm_error("CLONE", {"Unable to clone sequence item '",item.get_type_name(),"'"})
return 0;
end
// Check for TLM analysis ports
if(item_copy.get_type_name() == "uvm_tlm_analysis_port_base") begin
t = item_copy;
t.set_source_info(source_file, source_line);
t.analysis_imp.connect(item_copy.analysis_export);
t.write(t);
return 1;
end
// Set the item's sequencer
item_copy.set_sequencer(sequencer);
// Set the item's source info
item_copy.set_source_info(source_file, source_line);
// Set the item's priority
if (set_priority)
item_copy.set_priority(m_priority);
// If in a run phase, start the item
phase = comp.get_phase();
if (phase != null && phase.get_name() == "run") begin
if (!sequencer.start_item(item_copy)) begin
`uvm_error("NOSEQITEM", {"Failed to start sequence item ",
item_copy.get_type_name()," with sequencer ",
sequencer.get_type_name()})
return 0;
end
end
else
m_req_q.push_back(item_copy);
return 1;
endfunction
```
此函数接收四个参数:
- `item`:要插入序列执行队列中的序列化对象。
- `sequencer`:将序列化对象插入到其执行队列中的UVM序列器。
- `set_priority`:指示是否应将`item`的优先级设置为该序列的优先级。
- `source_file`和`source_line`:指示从哪个源代码文件和行开始创建序列化对象。
该函数首先检查传递的参数是否有效。然后,它会复制序列化对象并将其设置在传递的`sequencer`中。如果序列化对象是一个TLM分析端口,则该函数会将其连接到分析导出,并通过`write`函数写入分析对象。如果在运行阶段,则该函数将使用传递的`sequencer`启动序列化对象。否则,它将序列化对象插入到要求队列中。函数返回1表示成功,返回0表示失败。
相关推荐
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)