UVM实战_6_UVM中的factory机制

本文详细介绍了UVM中的factory机制,阐述了加入factory机制的优点,如自动创建类实例并调用函数。同时,文章探讨了System Verilog中的重载概念,包括任务、函数、约束的重载,并通过例子展示了如何使用factory进行重载。此外,还讲解了组件、对象的重载方式,复杂的重载场景,以及如何调试重载。最后,文中提到了在transaction、sequence和component中的重载应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

本章内容主要对UVM实战第8章的内容做出总结


一、加入factory机制及其优点

factory机制最神奇的一点:可以自动创建一个类的实例并调用其中的函数(function)和任务(task)。举例如下:

class my_driver extends uvm_driver;
   `uvm_component_utils(my_driver)  //将my_driver登记在UVM内部的一张表中,即加入factory机制
   function new(string name = "my_driver", uvm_component parent = null);
      super.new(name, parent);
      `uvm_info("my_driver", "new is called", UVM_LOW);
   endfunction
   extern virtual task main_phase(uvm_phase phase);
endclass

factory机制的实现被集成在了一个宏中:uvm_component_rtils,作用如下:

  1. 该宏将my_driver登记在UVM内部的一张表中
  2. 可以根据类名创建一个my_driver的实例,如在hw_tb中run_test(“my_driver”)
  3. 自动调用my_driver的main_phase

二、重载

1. system verilog对重载的支持

1.1 任务与函数的重载

重载:当在父类定义一个函数/任务时,如果将其设置为virtual类型,那么就可以在子类中重载这个函数/任务。
优势:重载的最大优势是使得一个子类的指针以父类的类型传递时,其表现出的行为依然是子类的行为。
举例如下:

class bird extends uvm_object;//父类
   virtual function void hungry();
      $display("I am a bird, I am hungry");
   endfunction
   function void hungry2();
      $display("I am a bird, I am hungry2");
   endfunction
   `uvm_object_utils(bird)
   function new(string name = "bird");
      super.new(name);
   endfunction 
endclass

class parrot extends bird;//子类
   virtual function void hungry();
      $display("I am a parrot, I am hungry");
   endfunction
   function void hungry2();
      $display("I am a parrot, I am hungry2");
   endfunction
   `uvm_object_utils(parrot)
   function new(string name = "parrot");
      super.new(name);
   endfunction 
endclass
...
function void my_case0::print_hungry(bird b_ptr);//表示能接收的函数类型是bird
   b_ptr.hungry();
   b_ptr.hungry2();
endfunction

function void my_case0::build_phase(uvm_phase phase);
   bird bird_inst;
   parrot parrot_inst;
   super.build_phase(phase);
 
   bird_inst = bird::type_id::create("bird_inst");
   parrot_inst = parrot::type_id::create("parrot_inst");
   print_hungry(bird_inst);//b_ptr指向的实例是bird类型,b_ptr本身也是bird类型
   print_hungry(parrot_inst);//b_ptr指向的实例是parrot类型,而b_ptr本身虽然是parrot类型,
   							//但是在调用hungry函数时,它被隐式地转换成了bird类型。打印结果如下:
   							//I am a parrot, I am hungry
   							//I am a bird, I am hungry2
endfunction

上述代码第40行,实际就是一个重载的过程,parrot是子类,bird是父类,parrot将bird重载,或者说parrot将bird覆盖。在这个过程中,将parrot.hungry函数覆盖了bird.hungry,因为hungry是virtual类型的,可以被覆盖。
所以,按照书中描述,parrot的指针parrot_inst是以父类(bird)的类型传递,其表现出来的行为依然是子类的行为,因为父类的hungry被子类的hungry覆盖了。

1.2 约束的重载

假如一个接收MAC功能的DUT,有多种异常情况需要测试,如preamble错误、sfd错误、CRC错误。这些错误都是异常的情况,在大部分测试用例中,它们的值应该为0。在异常的测试用例中,它们值应该为1。如何实现呢?有两种方法

第一:在定义transaction时,约束成0,在异常的测试用例中,使用`uvm_rand_send_with重新约束,代码如下:

class my_transaction extends uvm_sequence_item;
   ...
   constraint crc_err_cons{
   
      crc_err == 1'b0;
   } 
   constraint sfd_err_cons{
   
      sfd_err == 1'b0;
   } 
   constraint pre_err_cons{
   
      pre_err == 1'b0;
   } 
   ...
   `uvm_object_utils_begin(my_transaction)
      `uvm_field_int(dmac, UVM_ALL_ON)
      `uvm_field_int(smac, UVM_ALL_ON)
      `uvm_field_int(ether_type, UVM_ALL_ON)
      `uvm_field_array_int(pload, UVM_ALL_ON
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值