`uvm_send 和`uvm_do之间的关系
时间: 2024-01-26 07:04:49 浏览: 305
`uvm_send`和`uvm_do`都是UVM中用于驱动和监视器之间交互的方法,但它们的作用不同。
`uvm_send`用于在驱动中向监视器发送事务,它将事务放入到事务队列中,并返回一个布尔值表示是否成功发送。如果发送成功,那么监视器会在其`uvm_do`方法中接收到该事务。
`uvm_do`方法用于从监视器的事务队列中取出事务并进行处理。监视器在其`uvm_do`方法中使用`uvm_recv`方法从事务队列中取出事务并进行处理。当监视器处理完事务后,它可以使用`uvm_send`方法将响应事务发送回驱动。
因此,`uvm_send`和`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_send可以用什么代替
如果你正在使用的是 UVM 中的 `uvm_send` 方法,那么你可以考虑使用 `uvm_do` 方法来代替。`uvm_do` 方法是 UVM 中用于启动事务的一种方法,它可以在运行时动态地选择正确的端口和序列,并将事务发送到该端口。
使用 `uvm_do` 方法可以避免类型不匹配等问题,并且使代码更加简洁和易于维护。以下是一个使用 `uvm_do` 方法的例子:
```
my_sequence my_seq;
my_driver my_drv;
// Start the sequence by calling uvm_do
uvm_do(my_seq, my_drv);
```
在这个例子中,`my_seq` 是一个 UVM 序列对象,`my_drv` 是一个 UVM 驱动对象。通过调用 `uvm_do` 方法,可以启动 `my_seq` 序列并将其发送到 `my_drv` 驱动中进行处理。
阅读全文