目录

  • 1. 注册
  • 2. 创建
    • 2.1. 建议使用 drv = my_driver::type_id::create("drv",agt); 创建
    • 2.2. 使用factory创建
    • 2.3. 使用uvm_component方法创建
  • 3. 创建函数的重载
    • 3.1. 创建函数的重载方法
      • 一次重载
      • 连续重载
    • 3.2. 重载信息打印
    • 3.3. 组件重载分析
  • 4. 例子
    • 4.1. 重载`chnl_driver`中的`task do_drive();`
      • 分析

如果我们用Systemverilog构建验证平台,构建好了之后,想改变平台中的某个组件,例如将driver改成driver_new,我们需要重新定义一下driver_new,当然也可以直接从driver继承。但是我们还需要在driver对象例化的地方将driver drv;改成driver_new drv;,如果需要多个组件的更新、以及多次的平台复用,那代码量巨大,而且每次改变都要深入平台内部,非常繁琐。

基于上述问题,UVM提出了factory机制,译作工厂机制,来源于设计模式中的工厂机制。

factoy机制意思是:通过将拓展类在工厂注册,可实现环境内部组件的创建与对象的重载

factory机制主要针对构成验证环境层次的uvm_component及其子类,以及构成环境配置属性和数据传输的uvm_object及其子类

1. 注册

使用factory机制的第一步就是将类注册到工厂。这个factory是整个全局仿真中存在且唯一的“机构”,所有被注册的类才能使用factory机制。

使用宏进行注册

`uvm_component_utils(my_agent)                  //component注册macro
`uvm_component_utils_begin(my_agent)           //注册factory的同时,可注册field automation
//...
`uvm_component_utils_end`uvm_component_param_utils(my_driver)         //参数化的component注册,例class my_driver #(int width = 32) extends uvm_driver;
`uvm_component_utils_param_begin(my_driver)            //注册factory的同时,可注册field automation
//...
`uvm_component_utils_param_end`uvm_object_utils(my_transaction)               //object注册macro
`uvm_object_utils_begin(my_transaction)                //注册factory的同时,可注册field automation
//...
`uvm_object_utils_end`uvm_object_param_utils(my_sequence)         //参数化的object注册,例class my_sequence #(int width = 32) extends uvm_sequence;
`uvm_object_utils_param_begin(my_sequence)         //注册factory的同时,可注册field automation
//...
`uvm_object_utils_param_end

UVM-1.2中,这个所谓的全局唯一factory其实存在于uvm_coreservice_t类中,该类包含了UVM核心组件和方法。该类不是uvm_component和uvm_object型的,而是独立于UVM的。

2. 创建

创建就是实例化对象,所有注册到factory的类均可通过factory独特的方式实例化对象。

但factory的独特方式,实际上也是调用了new函数,也是先创建句柄再赋予对象。

例如

class my_agent extends uvm_agent;`uvm_component_utils(my_agent)                     //注册function new(string name, uvm_component parent);super.new(name,parent);endfunction//...
endclass
my_agent agt;                                           //创建my_agent句柄
agt = my_agent::type_id::create("agt", env);         //factory独特且最常用的例化方式,创建了my_agent实例并返回句柄,本质还是调用的my_agent::new(name,parent);class my_sequence extends uvm_sequence;`uvm_object_utils(my_sequence)                      //注册function new(string name);                          //object不属于uvm层次结构,不需要parentsuper.new(name);endfunction//...
endclass
my_sequence seq;                                    //创建my_sequence句柄
seq = my_sequence::type_id::create("seq");           //factory独特且最常用的例化方式,创建了name为"seq"的my_sequence实例,并返回句柄

2.1. 建议使用 drv = my_driver::type_id::create(“drv”,agt); 创建

简单好用。

简单好用,当然也有其他方法,不过可能涉及到$cast或是引入factory

2.2. 使用factory创建

提供了原型

  //...\questasim64_2020.1\verilog_src\uvm-1.2\src\base\uvm_factory.svhpure virtual functionuvm_object    create_object_by_type    (uvm_object_wrapper requested_type,  string parent_inst_path="",string name=""); pure virtual functionuvm_component create_component_by_type (uvm_object_wrapper requested_type,  string parent_inst_path="",string name, uvm_component parent);pure virtual functionuvm_object    create_object_by_name    (string requested_type_name,  string parent_inst_path="",string name="");

uvm_object_wrapper requested_type:用于表示对象类型

函数原型为

//...\questasim64_2020.1\verilog_src\uvm-1.2\src\base\uvm_object.svh
virtual class uvm_object extends uvm_void; extern static function uvm_object_wrapper get_type ();extern virtual function uvm_object_wrapper get_object_type ();...
endclass

其他形参,string parent_inst_pathstring nameuvm_component parent依次表示父节点路径(object不需要)、对象name、父节点句柄

直接使用factory方法创建,注意要用全局唯一uvm_factory类对象factory调用上述方法,并且上述方法返回类型不是uvm_object就是uvm_component,所以要用$cast作类型转换

例子如下

class my_test extends uvm_test;`uvm_component_utils(my_test);my_transaction t;...function void build_phase(uvm_phase phase);super.build_phase(phase);void'($cast(t,factory.create_object_by_type(my_transaction::get_type(),,"t")));         //注意使用void'()令返回为空...endfunction
endclass

2.3. 使用uvm_component方法创建

一般是在component内创建其他component或object,所以uvm_component类也提供了创建的方法

//...\questasim64_2020.1\verilog_src\uvm-1.2\src\base\uvm_component.svhextern function uvm_component create_component (string requested_type_name, string name);extern function uvm_object create_object (string requested_type_name,string name="");

也要注意使用$cast做类型转换

3. 创建函数的重载

重载的意思就是覆盖、替换。

对于UVM中的factory机制,可实现factory机制中创建函数的重载,即将父类的创建函数 重载成 子类的创建函数

也就是说,重载之后,父类的句柄指向的是子类的实例!!

前提是必须将父类和子类均在factory中注册,必须使用factory的例化方式。

component和object之间不能重载

例如

class bird extends uvm_object;`uvm_object_utils(bird);//...
endclassclass parrot extends bird;`uvm_object_utils(parrot);//...
endclass
function void my_case0::build_phase(uvm_phase phase);   //my_case0的build_phase方法bird bird_inst;parrot parrot_inst;bird_inst = new("bird_inst");                      //bird句柄指向了名叫"bird_inst"的bird对象,注意UVM中不允许这样例化!!parrot_inst = new("parrot_inst");                  //parrot句柄指向了名叫"parrot_inst"的parrot对象,注意UVM中不允许这样例化!!bird_inst = parrot_inst;                           //bird句柄指向了名叫"parrot_inst"的parrot对象,SV的多态//...
endfunctionfunction void my_case1::build_phase(uvm_phase phase);                        //my_case1的build_phase方法bird bird_inst;parrot parrot_inst;set_type_override_by_type(bird::get_type(),parrot::get_type());           //将父类bird重载成子类parrotbird_inst = bird::type_id::create("bird_inst");                      //注意,此处返回的是名叫"bird_inst"的parrot实例!但bird_inst依旧是bird句柄parrot_inst = parrot::type_id::create("parrot_inst ");//...
endfunction

注意,原验证环境都是通过父类句柄实现方法的,重载之后父类句柄指向的是子类对象,此时只有父类中为virtual型,且在子类中被重新实现的方法,原验证环境才会使用子类中的该方法。

可参考SystemVerilog HVL:面向对象编程(Object Oriented Programming, OOP)中Systemverilog中的多态的概念,就是指子类含有与父类同名的方法,且父类中该方法是虚方法virtual,则父类句柄可指向该子类对象,且通过父类句柄调用该虚方法时,实际上系统会调用子类的同名方法。

3.1. 创建函数的重载方法

除了可将所有的父类创建函数重载成子类创建函数,还可以仅针对某个特定的实例进行重载。甚至还支持连续重载。

一次重载

uvm_component提供了以下方法进行重载,重载和被重载的可以是uvm_object类型。

原型

//...\questasim\verilog_src\uvm-1.2\src\base\uvm_component.svh
extern static function void uvm_component::set_type_override(string original_type_name, string override_type_name,bit    replace=1);
extern function void uvm_component::set_inst_override(string relative_inst_path,  string original_type_name,string override_type_name);

例如

class my_case extends uvm_test;set_type_override_by_type(monitor1::get_type(),monitor2::get_type());                     //将monitor1类重载成monitor2类set_inst_override_by_type("env.o_agt.mon",monitor1::get_type(),monitor2::get_type());     //只将env.o_agt.mon的创建函数重载set_type_override("monitor1","monitor2");                                                   //用string描述类名set_inst_override("env.o_agt.mon","monitor1","monitor2");                                    //索引、string父类名,string子类名
//...
endclass

若是在component类外部,例如tb的initial 块内,无法调用uvm_component方法,可使用全局唯一uvm_factory对象factory进行重载,写法如下

原型

//...\questasim\verilog_src\uvm-1.2\src\base\uvm_factory.svhpure virtual functionvoid set_inst_override_by_type (uvm_object_wrapper original_type,uvm_object_wrapper override_type,string full_inst_path);pure virtual functionvoid set_inst_override_by_name (string original_type_name,string override_type_name,string full_inst_path);pure virtual functionvoid set_type_override_by_type (uvm_object_wrapper original_type,uvm_object_wrapper override_type,bit replace=1);pure virtual functionvoid set_type_override_by_name (string original_type_name,string override_type_name,bit replace=1);

例子

initial beginfactory.set_inst_override_by_type(monitor1::get_type(),monitor2::get_type(),"env.o_agt.mon"); factory.set_inst_override_by_name("monitor1","monitor2","env.o_agt.mon",);factory.set_type_override_by_type(monitor1::get_type(),monitor2::get_type());                       factory.set_type_override_by_name("monitor1","monitor2");                                                   end

uvm_component类内重载方法,本质上也是借用factory对象实现的。
uvm_factory类不从任何类拓展来,详见…\questasim\verilog_src\uvm-1.2\src\base\uvm_factory.svh

连续重载

即将父类的创建函数重载成子类的创建函数,还可将子类的创建函数继续重载成孙类的创建函数,以此类推。

class big_parrot extends parrot;`uvm_object_utils(big_parrot);//...
endclass
function void my_case1::build_phase(uvm_phase phase);                       bird bird_inst;parrot parrot_inst;big_parrot big_parrot_inst;set_type_override("bird","parrot");set_type_override("parrot","big_parrot");           bird_inst = bird::type_id::create("bird_inst");                      //bird句柄指向的是名叫"bird_inst"的big_parrot实例!parrot_inst = parrot::type_id::create("parrot_inst");                    //parrot句柄指向的是名叫"parrot_inst"的big_parrot实例!//...
endfunction

3.2. 重载信息打印

原型:

//...\questasim\verilog_src\uvm-1.2\src\base\uvm_component.svhextern function void print_override_info(string requested_type_name,string name="");
//...\questasim\verilog_src\uvm-1.2\src\base\uvm_factory.svhpure virtual functionvoid debug_create_by_type (uvm_object_wrapper requested_type,string parent_inst_path="",string name="");pure virtual functionvoid debug_create_by_name (string requested_type_name,string parent_inst_path="",string name="");extern  virtual function void print (int all_types=1);

例子如下

所有uvm_component类的重载信息打印:

function void my_case1::build_phase(uvm_phase phase);                        //...bird_inst = bird::type_id::create("bird_inst");bird_inst.print_override_info("bird");                         //打印重载信息,注意输入的是原始类型"bird"//...
endfunction

在component外部调用factory对象也可打印

initial begin                                                        factory.debug_create_by_name("my_monitor");                                               //打印my_monitor为父类的重载信息factory.debug_create_by_type(my_monitor::get_type(),"uvm_test_top.env.o_agt.mon");      //打印实例mon的重载信息factory.print(0);                                                                     //打印所有被重载实例和类型factory.print(1);                                                                     //打印所有被重载实例和类型,以及所有用户创建的、注册到factory的类名factory.print(2);                                                                      //打印所有被重载实例和类型,以及所有系统创建的、注册到factory的类名
end

3.3. 组件重载分析

当希望改变验证环境中的组件时,而又不改变原验证环境时,factory重载是最佳的方法,那该如何分析重载之后的验证组件呢?

抓住一点:只有原组件virtual方法重载之后才起作用

就是说父类重载出子类后,只有父类中virtual方法在子类中重新实现了,才会在原验证环境上体现出来

4. 例子

重载的意义就是更新、改变、替换。所以当原test中某个组件需要改变,但不能改变原组件的代码,可通过factory机制将原组件重载一个新的组件。

重载步骤很简单:重载旧类中的virtual方法

4.1. 重载chnl_driver中的task do_drive();

● 首先,原验证环境已经成熟

class chnl_driver extends uvm_driver #(chnl_trans);//...task run_phase(uvm_phase phase);forkthis.do_drive();//...joinendtaskvirtual task do_drive();//...endtask
endclass: chnl_driverclass agent extends uvm_agent;chnl_driver driver;//...function void build_phase(uvm_phase phase);super.build_phase(phase);driver = chnl_driver::type_id::create("driver",this);//...endfunction
endclassclass env extends uvm_env;//...
endclass
class base_test extends uvm_test;//...
endclass

● 然后我想修改原chnl_driver中的do_drive()方法,我就继承一个my_driver

class my_driver extends chnl_driver;//...task do_drive();//...endtask
endclass

● 之后创建一个属于我的my_test测试用例,在这里面使用factory机制重载。在tb中调用run_test("my_test");即可

class my_test extends base_test;//...function void build_phase(uvm_phase phase);super.build_phase(phase);set_type_override("chnl_driver","my_driver");//...endfunction
endclass

分析

按照上面的行为能否使用my_driver::do_drive()呢?作一下分析

首先在build_phase中,先调用base_test::build_phase,创建了env对象,然后执行factory重载,这样在创建chnl_driver对象时,就实现了chnl_driver句柄driver指向了my_driver对象。

然后在run_phase中,要执行的是chnl_driver::run_phase,中的chnl_driver::do_drive方法,但由于该方法是virtual型的而且指向的是子类的对象,就从子类中找方法,发现找到了my_driver::do_drive,所以执行的是子类的方法,重载成功。

但注意,如果父类中的非virtual方法被重载,或是在子类中创建了一个父类中不存在的方法,即使使用了factory覆盖,这两种情况也都不会在新的测试用例中实现。

UVM:factory 机制相关推荐

  1. UVM factory机制源码探微

    文章目录 1. UVM factory机制的使用 2. class 在factory 中的注册过程 2.1. `uvm_component_utils() 2.1.1. m_uvm_component ...

  2. UVM源码分析之factory机制详解

    前言 作者在学习了一段时间的UVM factory源码之后写下此文,旨在记录自己的学习成果,毕竟好记性不如烂笔头嘛,当然如果能帮助到对这部分有疑惑的同仁就更好了.作者是在笔记本电脑上的windows环 ...

  3. UVM中factory机制的使用

    UVM中的factory机制一般用在sequence的重载,尤其是virtual sequence.当Test_case变化时,通过virtual sequence的重载,可以很容易构建新的测试. 因 ...

  4. UVM的factory机制

    在UVM中使用工厂模式基本上分为三个步骤: 1. 注册 当定义一个类的时候,它的类型必须要注册,UVM已经提供了专用的宏. `uvm_component_utils(class_type_name) ...

  5. (7)UVM objection机制

    (7)UVM objection机制 objection机制 控制objection的最佳选择 UVM-1.1之后,结束仿真的机制有且只有一种,那就是利用objection挂起机制来控制仿真结束. o ...

  6. UVM config_db机制源码探微

    文章目录 1. uvm_config_db 基础 1.1. 简单set 1.2. 多重set 2. uvm_resource 2.1. uvm_resource_base 2.2. uvm_resou ...

  7. 02、UVM工厂机制

    一.工厂机制的意义 工厂机制也是软件的一种典型设计模式,UVM工厂的存在就是为了更方便地替换验证环境中的实例或者注册了的类型,同时工厂的注册机制也带来了配置的灵活性. 这里的实例或者类型替代,在UVM ...

  8. (3)UVM 工厂机制

    工厂机制 文章目录 工厂机制 一.工厂的意义 二.工厂机制 三.构建函数new 四.uvm_coreservice_t类 关注作者 工厂(factor)机制是UVM的真正魅力所在.工厂机制也是软件的一 ...

  9. UVM phase机制(一)

    UVM的执行严格按照phase机制在执行的,顺序是: ->build_phase ->connect_phase ->end_of_elaboration_phase ->st ...

  10. UVM: callback机制 uvm_callback和uvm_callbacks

    callback机制 callback机制提高代码的可重用性,还用于构建异常的测试用例. 广义的callback机制有post_randomize(),pre_body(),post_body(), ...

最新文章

  1. 利用三层交换机实现VLAN间路由
  2. Sonic 开源移动端云真机测试平台 - windows系统下的sonic快速部署演示
  3. 三种SQL分页查询的存储过程
  4. Spark学习之概念了解
  5. boost::mpl模块实现joint_view相关的测试程序
  6. .net core 微服务下的手工签名实现,以及消除中文乱码
  7. 【数据结构与算法】伸展树的Java实现
  8. Java GC 垃圾回收器
  9. 网易云音乐IPO拟至少募30.4亿港元 开售半日已获足额认购
  10. rds for mysql的监控指标_支持的监控指标_云数据库 RDS_用户指南_MySQL用户指南_监控指标与告警_华为云...
  11. mysql查询一周内的订单_MYSQL查询一周内的数据(最近7天的) 怎么写
  12. 最少钱币数-1-贪心算法(错,或者叫有问题)-CCF-CSP练习题(50)
  13. HTMLTestRunner文件
  14. MATLAB 转置与共轭转置、在legend中输入数字、求频偏的小收获
  15. QListView实现自定义Item
  16. 从零构建 React 开发环境(一) —— hello world,麻雀虽小五脏俱全~
  17. hdu 5510 Bazinga KMP+暴力
  18. 计算机安全标准是什么,计算机安全等级划分标准
  19. BAT程序员工作的真实情况
  20. arctanx麦克劳林公式推导过程_半桥 LLC 基波分析和参数计算过程推导

热门文章

  1. `node2vec` `TSNE` 待解决问题
  2. python时间序列预测不连续怎么办_用Python处理非平稳时间序列攻略
  3. 区间直觉模糊集相似度及matlab应用
  4. SSM房产中介管理系统
  5. uefi引导gpt安装win10_uefi安装win10系统原版镜像教程
  6. 学习Python爬虫有哪些书籍书籍?看这几本书就够了
  7. python建模的步骤_python基础教程之Python 建模步骤|python基础教程|python入门|python教程...
  8. java 数独 gui,GitHub - fagen/sudoku: 数独终局生成器和GUI
  9. 用阿里云盘,找不到资源怎么办???
  10. 神奇宝贝HTML游戏代码,《我的世界》神奇宝贝召唤神兽指令 各神兽召唤代码大全...