路科验证MCDF_uvmlab1

本文详细介绍了UVM验证环境中的工厂机制,包括组件和对象的注册、创建和覆盖,以及如何通过工厂进行类型重载。此外,还探讨了域自动化,展示了如何通过uvm_object_utils宏自动化处理成员变量,以及phase机制的作用和执行顺序。在配置机制部分,讲解了如何使用uvm_config_db进行接口、单一变量和配置对象的传递。最后,讨论了消息管理,包括如何通过设置报告级别和ID来过滤不必要的消息输出,以优化仿真效率。

一、工厂的注册、创建和覆盖机制

工厂机制_知识回顾

  • 背景:有时候无法直接修改验证平台的代码,比如①别人正在用,修改会影响别人使用;②验证IP你没有办法直接看到,所以也无法修改。
  • 作用:为了更方便地替代验证环境中的实例或者注册类型
  • 核心三要素:注册、创建、覆盖

1、注册:要用 uvm_component_utils()或者uvm_object_utils()注册

  • uvm_component常见的组件有:uvm_driver、uvm_monitor、uvm_sequencer、uvm_agent、uvm_scoreboard、uvm_env、uvm_test,凡是继承他们的组件都需要用 uvm_component_utils()进行注册;
    在这里插入图片描述

  • 除了上述提到的组件外,几乎所有的类都派生自uvm_object,常见的有uvm_sequence_item、uvm_sequence、config等

  • 引用《UVM实战》里的一段话来加深对uvm_object的认识:

uvm_object是一个分子, 用这个分子可以搭建成 许许多多的东西, 如既可以搭建成动物, 还可以搭建成植物, 更加可以搭建成没有任何意识的岩石、 空气等。 uvm_component就 是由其搭建成的一种高级生命, 而sequence_item则是由其搭建成的血液, 它流通在各个高级生命( uvm_component) 之间, sequence则是众多sequence_item的组合, config则是由其搭建成的用于规范高级生命( uvm_component) 行为方式的准则。

2、创建:UVM中创建实例的方法有很多,常用xxx::type_id::create来创建;注意,如果用new()来创建则无法使用工厂的覆盖
3、覆盖
覆盖并不是工厂机制的发明,所有面向对象的语言都支持函数/任务重载。
采用工厂进行覆盖有以下条件:

  • 原类型和新类型都需要注册到工厂里;
  • 需要用工厂机制来创建;
  • 覆盖的类和被覆盖的类有继承关系,并且被覆盖的方法要声明为virtual。不过有例外:component和object之间不能相互覆盖(虽然component是object的子类,但血缘关系太远了)

若有多层覆盖时,最终覆盖的类必须是最初被覆盖类的子类;多层覆盖,以最后一个覆盖结果为准

object_create

class object_create extends top;
    trans t1, t2, t3, t4;
    `uvm_component_utils(object_create)
    function new(string name = "object_create", uvm_component parent = null);
      super.new(name, parent);
    endfunction    
    function void build_phase(uvm_phase phase);
      uvm_factory f = uvm_factory::get(); // get singleton factory
      super.build_phase(phase);
      t1 = new("t1");   // direct construction
      t2 = trans::type_id::create("t2", this);//common method
      f.create_object_by_type(trans::get_type, get_full_name,"t3");//factory method
      create_object("trans","t4");// pre-defined method inside component
    endfunction
  endclass

说明:

  • get_full_name可以完整地得到当前component的路径
  • void’作用:减少编译器报warning,告诉编译器函数可能有返回值,但我不关心,将其转换为空值就行了
  • 参考代码里t3和t4加了动态转换cast,但好像没有什么必要,这里没有父类句柄指向子类对象的问题。这里加不加打印消息都一样。
void'($cast(t3,f.create_object_by_type(trans::get_type, get_full_name,"t3"))); 
void'($cast(t4,create_object("trans","t4")));  

仿真命令:

vsim -novopt -classdebug +UVM_TESTNAME=object_create work.factory_mechanism

仿真结果:
在这里插入图片描述
问:这里使用工厂创建时为什么名称没有传进去? 在仿真结果那里依然是trans type[trans] created,而不是trans type[t2] created;
答:questasim添加的uvm版本为1.2,所以有这个问题。最新uvm的版本已经解决这个问题。

component_create

class component_create extends top;
    unit u1, u2, u3, u4;
    `uvm_component_utils(component_create)
    function new(string name = "component_create", uvm_component parent = null);
      super.new(name,parent);
    endfunction

    function void build_phase(uvm_phase phase);
      uvm_factory f = uvm_factory::get();
      super.build_phase(phase);
      u1 = new("u1");
      u2 = unit::type_id::create("u2", this);
      void'(f.create_component_by_type(unit::get_type(),get_full_name,"u3",this));
      void'(create_component("unit","u4"));
    endfunction
  endclass

仿真命令:

vsim -novopt -classdebug +UVM_TESTNAME=component_create work.factory_mechanism

仿真结果
在这里插入图片描述

object_override

代码:

class object_override extends object_create;
    `uvm_component_utils(object_override)
    function new(string name = "object_override", uvm_component parent = null);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      set_type_override_by_type(trans::get_type(),bad_trans::get_type());
      super.build_phase(phase);
    endfunction
  endclass

仿真命令:

vsim -novopt +UVM_TESTNAME=object_override work.factory_mechanism

仿真结果:
在这里插入图片描述

component_override

class component_override extends component_create;
    `uvm_component_utils(component_override)
    function new(string name = "component_override", uvm_component parent = null);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      set_type_override("unit","big_unit");
      super.build_phase(phase);
    endfunction
  endclass

注意set_type_override_by_type()和set_type_override()的区别,前者函数内部要写类型,通过xx::get_type()获取,后者函数内部写类名,更方便。
仿真命令:

vsim -novopt +UVM_TESTNAME=component_override work.factory_mechanism

仿真结果:
在这里插入图片描述
结果分析:
在实例化时, UVM会通过factory机制在自己内部的一张表格中查看是否有相关的重载(也就是覆盖)记录。 set_type_override_by_type或者set_type_override语句相当于在factory机制的表格中加入了一条记录。 当查到有重载记录时, 会使用新的类型来替代旧的类型。以u2的覆盖为例。借助《uvm实战》p611页的图进行修改得到下图:
1
疑问:如果是按照上图进行判断的话,那感觉结果应该只会出现big_unit 类型,为什么还会出现unit类型的打印消息?
在这里插入图片描述
我在138、139行设了断点,并运行。
在这里插入图片描述
发现覆盖完,138行结束后,unit type和big_unit type是同时打印出来的,所以感觉真实的覆盖不是阻止unit类型的产生,而是通过将unit类型对应的句柄给到big_unit的对象来实现覆盖的。
在这里插入图片描述

二、域的自动化和uvm_object的常用方法

域的自动化_知识回顾

  • 作用:通过将成员变量在下方代码中进行注册,可以直接赋予变量常用的操作,比如复制、克隆、打印、比较等,节省了用户的编码时间
    `uvm_object_utils_begin(trans)
      `uvm_field_int(ARG, FLAG)//整形
      `uvm_field_enum(T, ARG, FLAG)//枚举
      `uvm_field_string(ARG, FLAG)//字符串
      `
评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hardworking_IC_boy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值