UVM中analysis端口的使用方法

UVM中有两种特殊的端口:analysis_port和analysis_export。这两者其实与put和get系列端口类似,都用于传递transaction。它们的区别是:
第一,默认情况下,一个analysis_port(analysis_export)可以连接多个IMP,也就是说,analysis_port(analysis_export)与IMP
之间的通信是一对多的通信,而put和get系列端口与相应IMP的通信是一对一的通信(除非在实例化时指定可以连接的数量,参照4.2.1节A_port的new函数原型代码清单4-4)。analysis_port(analysis_export)更像是一个广播。

第二,put与get系列端口都有阻塞和非阻塞的区分。但是对于analysis_port和analysis_export来说,没有阻塞和非阻塞的概念。
因为它本身就是广播,不必等待与其相连的其他端口的响应,所以不存在阻塞和非阻塞。一个analysis_port可以和多个IMP相连接进行通信,但是IMP的类型必须是uvm_analysis_imp,否则会报错。
对于put系列端口,有put、try_put、can_put等操作,对于get系列端口,有get、try_get和can_get等操作。对于analysis_port和
analysis_export来说,只有一种操作:write。在analysis_imp所在的component,必须定义一个名字为write的函数。

要实现图中所示的连接关系,A的代码为:

文件:src/ch4/section4.3/4.3.1/analysis_port/A.sv
3 class A extends uvm_component;
4   `uvm_component_utils(A)
5
6   uvm_analysis_port#(my_transaction) A_ap; //
…
13 endclass
…
20 task A::main_phase(uvm_phase phase); //
21   my_transaction tr;
22   repeat(10) begin
23     #10;
24     tr = new("tr");
25     assert(tr.randomize());
26     A_ap.write(tr); //
27    end
28 endtask

A的代码很简单,只是简单地定义一个analysis_port,并在main_phase中每隔10个时间单位写入一个transaction。B的代码为:

文件:src/ch4/section4.3/4.3.1/analysis_port/B.sv
3 class B extends uvm_component;
4 `uvm_component_utils(B)
5
6 uvm_analysis_imp#(my_transaction, B) B_imp; //
…
15 endclass
…
26 function void B::write(my_transaction tr); //
27   `uvm_info("B", "receive a transaction", UVM_LOW)
28   tr.print();
29 endfunction

如前所述,B是B_imp所在的component,因此要在B中定义一个名字为write的函数。在B的main_phase中不需要做任何操作。
C的代码与B完全相似,只要把相应的B替换为C即可。
env中的连接关系为:

//my_env.sv
29 function void my_env::connect_phase(uvm_phase phase);
30 super.connect_phase(phase);
31 A_inst.A_ap.connect(B_inst.B_imp);
32 A_inst.A_ap.connect(C_inst.C_imp);
33 endfunction

上面只是一个analysis_port与IMP相连的例子。analysis_export和IMP也可以这样相连接,只需将上面例子中的
uvm_analysis_port改为uvm_analysis_export就可以。
与put系列端口的PORT和EXPORT直接相连会出错的情况一样,analysis_port如果和一个analysis_export直接相连也会出错。只
有在analysis_export后面再连接一级uvm_analysis_imp,才不会出错。

现实情况中,scoreboard除了接收monitor的数据之外,还要接收reference model的数据。相应的scoreboard就要再添加一个
uvm_analysis_imp的IMP,如model_imp。此时问题就出现了,由于接收到的两路数据应该做不同的处理,所以这个新的IMP也要
有一个write任务与其对应。但是write只有一个,怎么办?
UVM考虑到了这种情况,它定义了一个宏uvm_analysis_imp_decl来解决这个问题,其使用方式为:

//my_scoreboard.sv
4 `uvm_analysis_imp_decl(_monitor) //
5 `uvm_analysis_imp_decl(_model)   //
6 class my_scoreboard extends uvm_scoreboard;
7 my_transaction expect_queue[$];
8
9 uvm_analysis_imp_monitor#(my_transaction, my_scoreboard) monitor_imp; //
10 uvm_analysis_imp_model#(my_transaction, my_scoreboard) model_imp;    //
…
15 extern function void write_monitor(my_transaction tr); //
16 extern function void write_model(my_transaction tr);   //
17 extern virtual task main_phase(uvm_phase phase);
18 endclass

上述代码通过宏uvm_analysis_imp_decl声明了两个后缀_monitor和_model。UVM会根据这两个后缀定义两个新的IMP类:
uvm_analysis_imp_monitor和uvm_analysis_imp_model,并在my_scoreboard中分别实例化这两个类:monitor_imp和model_imp。当与monitor_imp相连接的analysis_port执行write函数时,会自动调用write_monitor函数,而与model_imp相连接的analysis_port执行write函数时,会自动调用write_model函数。所以,只要完成后缀的声明,并在write后面添加上相应的后缀就可以正常工作了:

//my_scoreboard.sv
30 function void my_scoreboard::write_model(my_transaction tr);  //
31 expect_queue.push_back(tr);
32 endfunction
33
34 function void my_scoreboard::write_monitor(my_transaction tr); //
35 my_transaction tmp_tran;
36 bit result;
37 if(expect_queue.size() > 0) begin
…
55 end
56
57 endfunction
  • 6
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值