UVM:2.2只有driver的验证平台->2.2.4 加入virtual_interface

177 篇文章 139 订阅

1.前面的例子使用的是绝对路径,移植性差,因此用interface是极好的:

`ifndef MY_IF__SV
`define MY_IF__SV

interface my_if(input clk, input rst_n);

   logic [7:0] data;
   logic valid;
endinterface

`endif

2.例化DUT是可以直接连到端口上(systemverilog):

my_if input_if(clk, rst_n);
my_if output_if(clk, rst_n);

dut my_dut(.clk(clk),
           .rst_n(rst_n),
           .rxd(input_if.data),
           .rx_dv(input_if.valid),
           .txd(output_if.data),
           .tx_en(output_if.valid));

3.想在driver中使用,想当然的是在里面声明同样类型的变量,再赋值:

class my_driver extends uvm_driver;
   my_if  drv_vif;
..........................
endclass

1)但这样是报错的,在class中是不能声明一个interface的实参的,只有top_tb这种module可以。

2)即:在class中不能声明 一个占大面积内存的interface;最多声明一个virtual interface,这种同样类型的virtual变量,类似C语言的一个指针,把它的值赋为module中实参interface的地址。

3)UVM这么做的感觉和硬件的表现出奇一致。

3.1)硬件只有一个interface,想要接到这些信号的module一定要连上去才行;

3.2) UVM也一样,要想接到这个interface的class也只是声明个同样类型的virtual。把实参地址赋给它,最终还是有一个interface。

3.3)如果class中可以声明实参interface,再赋值,感觉也可以。但是整个UVM会有两个interface,与硬件不对应,不优雅;而且还浪费内存。幸好UVM会报错,根本不让这么做。


4所以要想下面这么做:

class my_driver extends uvm_driver;

   virtual my_if vif;

5. main_phase中赋值如下:

task my_driver::main_phase(uvm_phase phase);
   phase.raise_objection(this);
   `uvm_info("my_driver", "main_phase is called", UVM_LOW);
   vif.data <= 8'b0; 
   vif.valid <= 1'b0;
   while(!vif.rst_n)
      @(posedge vif.clk);
   for(int i = 0; i < 256; i++)begin
      @(posedge vif.clk);
      vif.data <= $urandom_range(0, 255);
      vif.valid <= 1'b1;
      `uvm_info("my_driver", "data is drived", UVM_LOW);
   end
   @(posedge vif.clk);
   vif.valid <= 1'b0;
   phase.drop_objection(this);
endtask

6.现在的问题是怎么把 top_tb 中的 input_if和my_driver中的vif连起来;或者说把实参interface的地址赋给virtual这个像pointer上。因为UVM建立了一个新的层次结构所以top_tb.my_driver.xxx是不行的。要用config_db,分为set 和get。

top_tb如下:

initial begin
   uvm_config_db#(virtual my_if)::set(null, "uvm_test_top", "vif", input_if);
end

my_driver如下:

virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      `uvm_info("my_driver", "build_phase is called", UVM_LOW);
      if(!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))
         `uvm_fatal("my_driver", "virtual interface must be set for vif!!!")
endfunction

1)build_phase 和 main_phase一样,也是UVM内建的phase。

2)UVM启动后,自动执行build_phase。

3)build_phase在new之后,main_phase之前执行。

4)build_phase做一些准备工作,主要通过config_db的set和get 传递变量,把整个UVM 的参数配置好,再让main_phase运行。

5)需要加入super.build_phase,因为其父类的build_phase执行一些必要操作,需显示调用。那是先执行父类还是本身呢?因该是父类把,super在最前。

6)build_phase是函数phase,不消耗仿真时间,(运行之前,配置参数用);main_phase是任务phase,总在仿真时间为0时执行。($time 可以看到,之前没有objection也可以证明)。和verilog中function 不消耗时间,task 消耗时间的概念相同。

7)config_db的set 和 get 第三个参数必须完全一致(synopsys也是这么说的)。set 的第二个参数表示路径索引。

8)set 和 get使用双冒号因为两个都是静态函数,uvm_config_db #() 传参是类型,即寄信种类。

9)get的时候以uvm_test_top的名字到数据库去找。


7.问题:

set 的第三个参数 “vif”,是放到数据库的标志,可以随便起;还是因为 my_driver 中也定义了vif,所以一定要一样呢?验证一下:

top_tb.sv改成如下:



为避免my_driver报错,把所有 vif 关于代码都去掉:



编译,仿真通过。打印所有信息。可见 set 的时候是不管是否存在真正的UVM索引。就像是直接写到了第三方的数据库。


8.my_driver中 get的第三个参数改成testvif应该可以吧。


编译仿真通过,信息打印,数据发出。没有问题。


9.get怎么写能通过 bbb.aaa 找到interface 呢?


10.如果是ccccc 的方法呢?


编译报错:


1)bit[39:0] 什么错误??。。看不懂

2)如果把ccccc 换成 ccc 。就是bit[23:0]什么错误? 看不懂。。。




  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值