1 UVM组件

1.1 vif(virtual interface)

从根本上来说,应该尽量杜绝在验证平台中使用绝对路径。避免绝对路径的另外一种方式是使用interface。

例:定义了interface后,在top_tb中实例化DUT时,就可以直接使用。

# xxx_if.sv interface xxx_if; logic sig_clk; logic sig_rst; logic sig_data; logic [6:0] sig_crc; endinterface: xxx_if # top_tb.sv crc7 dut(vif.sig_clk, vif.sig_rst, vif.sig_data, vif.sig_crc);

在driver中使用interface需要声明virtual interface

virtual xxx_if vif;

之后就可以在main_phase中使用vif类来驱动其中的信号。

virtual task drive(); ... vif.data = 1'b0; vif.rst = 1'b0; ... endtask: drive

1.2 transaction

transaction是一个抽象的概念。

一般来说,物理协议中的数据交换都是以帧或者包为单位的,通常在一帧或者一个包中要定义好各项参数,每个包的大小不一样。

很少会有协议是以bit或者byte为单位来进行数据交换的。

  • my_transaction的基类是uvm_sequence_item。在UVM中,所有的transaction都要从uvm_sequence_item派生,只有uvm_sequence_item派生的transaction才可以sequence机制。
  • 没有使用uvm_component_utils宏而是使用了uvm_object_utils来实现factory机制。从本质上来说,transaction与 driver是有区别的,在整个仿真期间,my_driver是一直存在的,my_transaction则有生命周期。它在仿真的某一时间产生,处理运行之后其生命周期就结束了。派生自uvm_object的类都要使用 uvm_object_utils宏来实现。

1.3 agent

1.3.1 agent:env

env是一个容器类,在这个容器类中实例化drivermonitorreference modelscoreboard等。

class xxx_env extends uvm_env; `uvm_component_utils(my_env) my_driver drv; function new(string name = "my_env", uvm_component parent); super.new(name, parent); endfunction virtual function void build_phase(uvm_phase phase); super.build_phase(phase); drv = my_driver::type_id::create("drv", this); endfunction endclass: xxx_env

实例化组件时没有直接调用其new函数,而是使用了一种古怪的方式。这种方式就是factory机制带来的独特的实例化方式。只有使用factory机制注册过的类才能使用这种方式实例化。才能使用factory机制中最为强大的重载功能。

验证平台中的组件在实例化时都应该使用type_name::type_id::create的方式。

在drv实例化时,传递了两个参数,一个是名字,另外一个是this指针,表示my_env:

c7_agent = crc7_agent::type_id::create (.name("c7_agent"), .parent(this)); c7_sb = crc7_scoreboard::type_id::create (.name("c7_sb"), .parent(this));

同时,top_tb.svrun_test的参数也从my_driver变为了my_env

1.3.2 agent:monitor

验证平台必须监测DUT的行为,只有知道DUT的Input/Output变化之后,才能根据这些信号变化来判定DUT的行为是否正确。

class my_monitor extends uvm_monitor; virtual my_if vif; `uvm_component_utils(my_monitor) function new(string name = "my_monitor", uvm_component parent = null); super.new(name, parent); endfunction virtual function void build_phase(uvm_phase phase); ... endfunction task main_phase(uvm_phase phase); ... endtask:main_phase task collect_one_pkt(my_transaction tr); ... endtask:collect_one_pkt endclass

uvm_monitor在整个仿真中是一直存在的,所以它是一个component,要使用uvm_component_utils宏注册。

1.3.3 agent

drivermonitor之间存在联系,因为两者之间的代码高度相似。其本质是因为二者

处理的是同一种协议,在同样一套既定的规则下做着不同的事情。

class my_agent extends uvm_agent ; `uvm_component_utils(my_agent) my_driver drv; my_monitor mon; function new(string name, uvm_component parent); super.new(name, parent); endfunction ... endclass

由于agent的加入,driver和monitor的层次结构改变了,在top_tb中使用config_db设置if时要注意改变路径。

UVM中约定俗成的还是在build_phase中完成实例化工作。因此,强烈建议仅在build_phase中完成实例化。

1.4 reference model

reference model用于完成和DUT相同的功能。

reference model的输出被scoreboard接收,用于和DUT的输出相比较。DUT如果很复杂,那么reference model也会相当复杂。

my_scoreboard要比较的数据来源:

  • 一是来源于reference model
  • 二是来源于dut输出数据后的的monitor(monitor_before)。

前者通过exp_port获取,而后者通过act_port获取。

最后修改:2022 年 03 月 28 日
如果觉得我的文章对你有用,请随意赞赏