- SV的核心特性包括面向对象、随机约束、线程通信、功能覆盖率收集等。详细内容可见:SystemVerilog学习笔记(全)
1.UVM概述
- UVM首先是一种方法学,并不是必须要与某一种语言绑定,吸取eRM,AVM,OVM,UVM等不同方法学的优点。
- 验证方法学服务目的在于提供一些可以重用的类来减轻项目之间水平复用和垂直复用的工作量。
- UVM面向所有数字设计,涵盖了从模块级到芯片级,ASIC到FPGA以及控制逻辑、数据通路到处理器验证的全部场景。
2.类库地图
UVM类库地图按照核心机制分为十大类:
- 核心基类(
uvm_object
):提供最底层的支持,包括如拷贝、创建、比较和打印等基本方法。 - 工厂类(
uvm_factory
):提供注册环境组件、创建组件和覆盖组件类型的方法。 - 事务和序列类:规定在TLM传输管道中的数据类型和数据生成方式。
- 结构创建类
- 环境组件类
- 通信管道类:与事务接口类共同实现组件之间的通信和存储。
- 信息报告类:使得UVM环境报告信息一致规范化。
- 寄存器模型类:对寄存器和存储的建模、访问和验证。
- 线程同步类
- 事务接口类
3.工厂机制
- UVM工厂的存在就是为了更方便地替换(覆盖)验证环境中实例或者注册了的类型。
- UVM的验证环境构成可以分为两部分,一部分通过
uvm_component
构成了环境的层次;另一部分通过uvm_object
构成环境的属性(配置)和数据传输。其中uvm_component
继承于uvm_object
,这两种类也是进出工厂的主要模具和生产对象。 - 两种范式:
//component
class comp1 extends uvm_component; //定义class
`uvm_component_utils(comp1) //注册到工厂
function new(string name="comp1", uvm_component parent=null); //必须包含两个参数
super.new(name, parent);
$display($sformatf("%s is created", name));
endfunction
endclass
//object
class obj1 extends uvm_object;
`uvm_object_utils(obj1) //注册
function new(string name="obj1"); //只包含一个参数
super.new(name);
$display($sformatf("%s is created", name));
endfunction
endclass
- 创建对象:
comp_type::type_id::create(string name, uvm_component parent);
object_type::type_id::create(string name);
// other create method 1
void'($cast(name, create_component("comp_type", string name));
void'($cast(name, create_object("object_type", string name));
// method 2
uvm_factory f = uvm_factory::get();
void'($cast(name, f.create_component_by_type(comp_type::get_type(), get_full_name(), string name, this)));
void'($cast(name, f.create_object_by_type(object_type::get_type(), get_full_name(), string name)));
- 运用工厂的步骤一般为:1)将类注册到工厂;2)在例化前设置覆盖对象和类型;3)对象创建。
- ⭐
uvm_coreservice_t
类内置了唯一的uvm_factory
、全局的report_server
、全局的tr_database
等UVM核心的组件和方法。该类没有例化在UVM环境中,而是独立于UVM环境之外,UVM系统在仿真开始时会将其例化一次。
4.覆盖方法(override)
- 要想实现覆盖特性,原有类型和新类型均需要注册。当使用
create()
创建对象时,工厂将检查原有类型是否被覆盖。 - 覆盖方法包括类型覆盖(UVM层次结构下所有原有类型都被覆盖类型所替换)和实例覆盖(在某些位置中的原有类型会被覆盖类型所替换)。
- 覆盖方法:
//static function
orig_type::type_id::set_type_override(new_type::get_type())
orig_type::type_id::set_inst_override(new_type::get_type(), "orig_inst_path") //缺省则inst_path为绝对路径;否则用{parent.get_full_name(),'.',inst_path}作为目标路径
// other override method
set_type_override_by_type(orig_type::get_type(), new_type::get_type());
- 覆盖实例:
// ... comp2 extends comp1;
comp1 c1, c2;
initial begin
comp1::type_id::set_type_override(comp2::get_type()); //只能影响通过工厂创建的对象
c1 = new("c1");
c2 = comp1::type_id::create("c2", null); //返回comp2的句柄,子类句柄赋给父类句柄
c1.xx();
c2.xx(); //xx在comp1类中为virtual虚方法
end
※ 需要注意的是comp2需要为comp1的子类,这样句柄的指向才是安全合法的;xx方法在父类comp1中应声明为虚方法c2的调用才可能正确。另外,覆盖方法应发生在对象创建之前。