芯片家 • 来自相关话题

4月前

最近做的ECO和如何使用verdiload原理图辅助做ECO

        好几年没做过ECO了,再次做起来比较痛苦,有一种清零后重新捡起来的感觉。笨办法做ECO当然是对照网表和RTL,把网表相关寄存器的逻辑都画出来,然后化简分析,找打做ECO的点,然后再手工做。但是曾经在上一家 ...查看全部

        好几年没做过ECO了,再次做起来比较痛苦,有一种清零后重新捡起来的感觉。笨办法做ECO当然是对照网表和RTL,把网表相关寄存器的逻辑都画出来,然后化简分析,找打做ECO的点,然后再手工做。但是曾经在上一家公司(业内养老单位,已经倒闭)做ECO的时候好歹是用“先进”的verdi工具辅助做。不必说用nECO里面的tcl脚本做,起码能帮忙load fan-in/out-core,加速分析吧。
        但是我在使用verdi工具上摔了跟头,不知道怎么load那种带原理图的netlist,奈何问了几个老同事也都告诉我verdi load了网表自然就有那种与非门图形库了。现在我想告诉这几个老同事“编,使劲编”,根本就是大家作为大公司的designer,不管flow,人家都给做好了,你load进来看起来都是好的,实际上verdi是需要load netlist+symbol_lib才能展示如下可爱的模样:

1.jpg

不然只load netlist,就是这个鬼样子:

2.jpg

     不买关子了,怎样建立图形库呢? verdi提供了一个工具,叫做syn2SymDB,这个工具可以把S公司的库转换成symbol库给verdi使用。

在我的main tree目录/proj/usr/my_main 执行如下命令
syn2SymDB -o tsxx_xx *.tsxx.0pxv?00c.lib.gz *.tsxx_FTx.0pxv?00c.lib.gz
setenv NOVAS_LIBS tsxx_xx
setenv NOVAS_LIBPATHS /proj/usr/my_main
然后再用verdi load 网表,找到你关心的逻辑单 元,再去tools->new schemetic->fan-out-core之类的,漂亮的带与或非门的原理图就呈现出来了。
同时顺便总结下此次ECO的教训,对比RTL前后改动,找到需要修改的点,注意:
1. 改动不要影响其它寄存器,看看你的改动点所有扇出,改动完了之后再检查一遍(load到verdi之类的工具里trace一遍)
2. 如果报了falling point点,有可能是以下原因:
a. 理解错或者用错cell了,在tech/verilog/stdcell/目录里一般有(我这次就用错了,该是与非门ND2,用成了与门 AND2)
b. 你的改动影响到了别的寄存器(我这次n42578改动是给A寄存器的,结果影响到了另外一个寄存器B)
c. 少改了某一处,所以还要反复对照前后改动的RTL(这次我发给flow owner的信里列举的RTL改动点就没列举完全)

admin • 来自相关话题

4月前

内推联盟需要你

亲爱的ICers,内推联盟现在有大量的优质IC简历,他们需要换工作,涵盖数字设计,数字验证,射频, 模拟等方向。现在急需大公司朋友们的加入,只要您们所在大公司有推荐奖励,都可以联系我们,让你赚钱,详情请咨询我们。希望感兴趣的IC工程师联系我们。微信号:chip ...查看全部

亲爱的ICers,内推联盟现在有大量的优质IC简历,他们需要换工作,涵盖数字设计,数字验证,射频, 模拟等方向。现在急需大公司朋友们的加入,只要您们所在大公司有推荐奖励,都可以联系我们,让你赚钱,详情请咨询我们。希望感兴趣的IC工程师联系我们。

微信号:chipist1   

Maggie • 来自相关话题

4月前

关于芯片验证的感悟

 18年下半年参与了某款5G芯片验证的开发过程,空余时间总结一下: 由于现在芯片的规模越来越大, 所以导致芯片验证的工作也越来越重要。 传统的通过写TB 的方式来测试芯片设计功能的方式也越来越吃力,而通过UVM的方式来进行芯片验证已经成为业 ...查看全部

 18年下半年参与了某款5G芯片验证的开发过程,空余时间总结一下:

 由于现在芯片的规模越来越大, 所以导致芯片验证的工作也越来越重要。 传统的通过写TB 的方式来测试芯片设计功能的方式也越来越吃力,而通过UVM的方式来进行芯片验证已经成为业界主流的验证方式。

 使用UVM的方式可以编写任意多个test case 配合对应的 sequence ,加上shell 脚本的辅助,可以在线切换任意的phase场景进行测试,增加了验证的自动化和灵活性,功能覆盖性也大大增强。

1. UVM 验证平台的搭建。

 一个UVM 验证仿真平台的搭建 ,需要一个整体的tb顶层来进行DUT 的封装,时钟和复位的激励生成,以及数据的DUMP 操作,应用的 virtual interface (VIF) 和 总线接口(AXI)的构建和初始化,以及和DUT的接口连接。  

 接下来编写各个应用场景对应的sequence 和test case ,通过 UVM的机制来进行指定test case 的仿真运行和测试。

 sequence 主要负责 参数的随机化生成,寄存器值的初始化,以及仿真的运行时间控制;test case 主要负责 UVM ENV component的初始化,以及在 main phase 中 通过对应的 sequence 来手动开启(关闭) 整个UVM平台的运行(采用 raise objection的方式)。这里可以采用基类构建框架, 继承类 实现具体动作的方式来增加灵活性。 我们这里还在sequence body 里面,调用了refer-C DPI 的功能,来运行C 功能。

  env component 模块主要负责各个子component(agent , moniter ,scoreborad )的集成, 这里我们使用了AXI 总线,所以这里我们也集成了AXI的一些模块(register model , adapter , VIP )。agent component 集成了sequencer 和 driver 组件 ,sequencer模块功能比较简单,负责将sequence 里面的transcation形式的数据发送给 driver ;driver组件总要负责将transcation形式的数据解析给 virtual interface ,进而传输给了DUT 。

  moniter 组件负责将DUT 的输出打包成transaction的形式,传送给scoreboard 组件。

  scoreboard组件负责 将DUT 的数据存储到queue中,同时将refer-C 输出存储到queue中,完成数据的比对。

无标题.png

1.2 寄存器读写 

  这里 主要讨论 AXI的寄存器读写 。由 sequence来完成数据的随机化操作 ,然后写到 register model 中,通过 adapter 来完成 总线和寄存器的转换,最后传送到 VIP 中,输出以 axi_vif 的形式传送给DUT的 AXI 接口。

2.png

1.3 phase的理解

   对于UVM中的component , phase的理解 才能正确使用各个组件。

   build phase 主要 完成 组件内各个子组件的创建 ;

   connect phase 主要完成 该组件与外部组件的连接;

   无时钟消耗的phase:build phase ,connect phase ,before simulation 

   在 sequence raise_objection 某一个 sequencer 后,在各个组件的main_phase 产生时钟消耗。

   关于 main_phase 的流水线设计 :

   这里 需要知道 UVM各个组件是长久活动的,在各个组件main_phase 中也需要 设计成 RTL流水线形式:

   在main_phase 采用 fork  ··· join 来保证先进行具体活动的实行 ;采用 forever  @posedge(clk) 来进行流水线设计 (等同于 RTL 设计的 always@(posedge clk ))

   在 sequence drop objection 来关闭 。

1.4 refer-c 和DPI 接口设计  

   SV 方面:

   如果SV 和 C++ 交互为对象 :import “DPI-C" function chandle getWrapperInstance() ; 来获取对象 ;

   如果SV 和C++ 交互为函数:import "DPI-C" function void systemSetup (input chandle systemInst ,...) 来传送数据给refer-C

   C/C++ 方面:

   添加与SV交互的接口代码 :dpi_main.cpp

   修改C/C++ 代码,GDB 调试 ,最后集成到 UVM 中 

   Makefile :

   添加输入参数给 SV ,环境配置  

   shell:

   test case 的自动化配置,参数传递给 Makefile

菜菜 • 来自相关话题

4月前

成都、厦门--模拟ic设计工程师,模拟版图工程师

微信:861112547成都厦门--模拟ic设计工程师,模拟版图工程师,欢迎推荐

微信:861112547



成都厦门--模拟ic设计工程师,模拟版图工程师,欢迎推荐

左拉呀 #招聘 • 来自相关话题

4月前

北京智能可穿戴创新公司-Digital Verification Engineer  

岗位Digital Verification Engineer Design and Integration Engineer 要求:5年以上,有RISC-V经验者优先欢迎详细了解微信:1370621224 ...查看全部

岗位

Digital Verification Engineer

 

Design and Integration Engineer

 

要求:5年以上,有RISC-V经验者优先

欢迎详细了解

微信:1370621224

Maggie • 来自相关话题

4月前

Testbench/UsingFactoryOverrides

       UVM factory允许在构造时将类替换为派生类型的另一个类。这对于通过将一个类替换为另一个类而无需编辑或重新编译测试平台代码来更改测试平台的行为来说是非常有用的。为了使factory重载过程起作用,需要 ...查看全部

       UVM factory允许在构造时将类替换为派生类型的另一个类。这对于通过将一个类替换为另一个类而无需编辑或重新编译测试平台代码来更改测试平台的行为来说是非常有用的。为了使factory重载过程起作用,需要遵循许多编码约定先决条件,这些在UVM factory的文章中进行了解释。
       UVM factory可以被认为是查找表。当使用 :: type_id :: create(“”,)方法(approach)进行“普通”组件构造时,会发生的是type_id用于为类选择factory组件包装器, 构造其内容并再次传回结果句柄。factory重载更改了查找的发生方式,因此查找原始的type_id会导致使用不同的type_id。因此,返回不同类型的构造对象的句柄。此技术依赖于多态性,即能够使用基本类型句柄引用派生类型的能力。实际上,只有当父类被类扩展层次结构中的一个子类重载时,重载才会起作用。

       Component Overrides 

     UVM中有两种类型的组件重载 - type overrides 和 instance overrides。  

       Component Type Overrides  

       type override意味着每次在测试平台层次结构中创建组件类type时,都会在其位置创建替换type。这适用于该组件类型的所有实例。以下代码片段中说明了此类重载的方法调用:

       // 
       // Component type override example 
       // ---------------------------------------------

       // Colour parent class 
       class colour extends uvm_component;

       `uvm_component_utils(colour)

       //etc
       endclass: colour

       // Red child class 
       class red extends colour;

       `uvm_component_utils(red)

       //etc 
       endclass: red

       // 
       // Factory type override syntax is: 
       // 
       // ::type_id::set_type_override(::get_type(), replace);
       //
       // Where replace is a bit which when ==1 enables the override of an existing override, otherwise
       // the existing override is honoured.

       // To override all instances of colour with red:
       colour::type_id::set_type_override(red::get_type(), 1);

       // This means that the following creation line returns a red, rather than a colour
       pixel = colour::type_id::create("pixel", this);

       参数化组件类也可以被重载,但必须注意确保重载类具有与被重载的类相同的参数值,否则它们不被认为是相关types:

        // 
        // Type overrides for parameterised classes: 
        // ----------------------------------------------------------

        // Base class type 
        class bus_driver #(int BUS_WIDTH = 32) extends uvm_component;

        `uvm_component_param_utils(bus_driver #(BUS_WIDTH))
        // etc

        endclass: bus_driver

        // Derived class type 
        class bus_conductor #(int BUS_WIDTH = 32) extends bus_driver #(BUS_WIDTH);

        `uvm_component_param_utils(bus_conductor #(BUS_WIDTH)) 
        // etc

        endclass: bus_conductor

        // The parameterised type override needs to keep the parameterisation consistent【重点记录下】

        bus_driver #(64)::type_id::set_type_override(bus_conductor #(64)::get_type(), 1); // This will succeed

        // Creation of a #(64) bus_driver results in a #(64) bus_conductor handle being returned:

        bus_person = bus_driver#(64)::type_id::create("bus_person", this);

        // Whereas creating a #(16) bus_driver results in a #(16) bus_driver handle being returned because
        // the matching type override is not found:

        bus_person = bus_driver#(16)::type_id::create("bus_person", this);

        // Similarly if a type override has non-matching parameters, then it will fail and return the original type

        bus_driver #(64)::type_id::set_type_override(bus_conductor #(32)::get_type(), 1); // Returns bus_driver #(64)
       

        Component Instance Overrides

        可以通过在uvm组件层次结构中指定其位置来重载特定组件实例。同样,这种方法可以与参数化类一起使用,只要注意匹配重载中涉及的两个类类型的参数:

        // 
        // Component Instance Factory Override example 
        // --------------------------------------------

        // Using red --> colour example from type override example 
        // 
        // Syntax for the instance override:
        //
        // ::type_id::set_inst_override(::get_type(), );
        //

        colour::type_id::set_inst_override(red::get_type(), "top.env.raster.spot");

        // And again for a parameterised type, the parameter values must match

        bus_driver #(64)::type_id::set_inst_override(bus_conductor #(64)::get_type(), "top.env.bus_agent.m_driver");

        Object Overrides

      Objects or sequence 相关 objects通常仅与type重载一起使用,因为instance重载方法涉及UVM测试平台组件层次结构中哪些objects不参与的位置。然而,有一个编码技巧可用于重载object的特定“instances”,这在overriding sequences的文章中有解释。

       object 重载的代码遵循与组件重载相同的形式。

Maggie • 来自相关话题

4月前

Testbench/SystemVerilog Packages

包是SystemVerilog语言结构,它使相关的声明和定义能够在包名称空间中组合在一起。包可能包含类型定义,常量声明,函数和类模板。为了能在一个范围内使用包,必须先导入它,然后才能引用其内容。     &nb ...查看全部

包是SystemVerilog语言结构,它使相关的声明和定义能够在包名称空间中组合在一起。包可能包含类型定义,常量声明,函数和类模板。为了能在一个范围内使用包,必须先导入它,然后才能引用其内容。
       包是组织代码的一种有用方法,也是确保对类型、类等的引用是一致的有用方法。UVM基类库包含在一个名为“uvm_pkg”的包中。在开发UVM测试平台时,应该使用包来收集和组织各种类定义,这些类定义是为实现agent、envs、sequence libraries、 test libraries等而开发的。 

       UVM Package Coding Guidelines 

      Package naming and file naming conventions: 

       应使用_pkg 后缀命名包。包含该包的文件的名称应反映包的名称,并具有.sv扩展名。【如YnrrubysimTestTop.sv文件中包含一个包,名字是package  YnrrubysimTestTop】
      例如:文件spi_env_pkg.sv将包含spi_env_pkg包。
      Justification:.sv扩展名是一种约定,表示包文件是独立的编译单元。_pkg 后缀表示该文件包含一个包。这两个约定对人类和机器解析脚本都很有用。

      Classes contained within a package should be `included 

      在包范围内声明的类模板应该分成具有.svh扩展名的单个文件。这些文件应该按照需要编译的顺序包含在包中【使用`include】。包文件是唯一应该使用`includes的地方,被'include的文件中不应该包含其他`include语句。
      Justification:.将类声明在单独的文件中使它们更易于维护,并且还使包内容更清晰。

      Imports from other packages should be declared at the head of the package

      包的内容可能需要引用另一个包的内容。在这种情况下,外部包应该在包代码体的开头声明。单个文件(例如可能被`include的类模板)不应单独导入。
      Justification:.将所有imports分组到一个地方可以清楚地了解包依赖那些文件或外部包。将imports放置在包的其他部分或内部被include的文件中,这可能会导致排序和潜在的类型冲突。

      All the files used by a package should be collected together in one directory

      要包含在包中的所有文件应该一起收集在一个目录文件夹中。这对于agents来说,它的目录结构需要是完整的独立包,这点尤为重要。
      Justification:.这使编译更容易,因为只有一个include目录,它还有助于重用,因为包的所有文件可以很容易地收集在一起。
      下面是UVM env的包文件示例。这个env包含两个agent(spi和apb)和一个寄存器模型,这些作为子包导入。与env相关的类模板被`include。

       // Note that this code is contained in a file called spi_env_pkg.sv 
       // 
       // In Questa it would be compiled using:
       // vlog +incdir+$UVM_HOME/src+  /spi_env_pkg.sv
       //

       //
       // Package Description:
       //
       package spi_env_pkg;

       // Standard UVM import & include:
       import uvm_pkg::*; 
       `include "uvm_macros.svh"

       // Any further package imports:
       import apb_agent_pkg::*; 
       import spi_agent_pkg::*; 
       import spi_register_pkg::*;

       // Includes:
       `include "spi_env_config.svh"
       `include "spi_virtual_sequencer.svh"
       `include "spi_env.svh"

       endpackage: spi_env_pkg

       Package Scopes

      经常让用户感到困惑的是SystemVerilog package是一个范围。这意味着在package中声明的所有内容以及导入到package中的其他package的内容仅在本package的范围内可见。如果将包导入另一个范围(即另一个包或模块),则只能看到包的内容,而不是它导入的任何包的内容。如果新范围中需要这些其他包的内容,则需要单独导入它们。

       // 
       // Package Scope Example
       // ---------------------------------------------------- 
       //
       package spi_test_pkg;

       // The UVM package has to be imported, even though it is imported
       // in the spi_env package. This is because the import of the uvm_pkg 
       // is only visible within the current scope
       import uvm_pkg::*;
       // The same is true of the `include of the uvm_macros
       `include "uvm_macros.svh"

       // Import of uvm_pkg inside the spi_env package is not 
       // visible within the scope of the spi_test package
       import spi_env_pkg::*; 

       // Other imports 
       // Other `includes
       `include spi_test_base.svh

       endpackage: spi_test_pkg

Maggie • 来自相关话题

4月前

SystemVerilog的文件读取方法

最近需要需要用sv读取文件,然后设定环境参数的问题。用$fscanf和$feof结合的方式解决了。具体做法如下:integer fd;string name;reg value;reg setting_value;fd=$fopen("ABC.txt","r" ...查看全部

最近需要需要用sv读取文件,然后设定环境参数的问题。

用$fscanf和$feof结合的方式解决了。

具体做法如下:

integer fd;

string name;

reg value;

reg setting_value;

fd=$fopen("ABC.txt","r");

while(!$feof(fd))begin

     $fscanf(fd, "%s %d", name, value);

     $display( "%s %d", name, value);

     if(name == "my_name") begin

        setting_value = value;

        break;

     end

end

ABC.txt的文件内容每行都是字符串+数字组成:

string_A 1

srting_B 0

...

总结:无论是C++还是perl等脚本,读取文件内容方式都是差不多的,大同小异。

Maggie • 来自相关话题

4月前

静态时序分析基础

建立时间,保持时间    为了确保寄存器在时钟沿稳定采集数据,那么必须要满足寄存器的建立,保持时间要求。建立时间要求:在寄存器有效时钟沿之前至少Tsetup时间,数据必须到达且稳定。如下图所示。     保持时 ...查看全部

建立时间,保持时间
    为了确保寄存器在时钟沿稳定采集数据,那么必须要满足寄存器的建立,保持时间要求。

建立时间要求:在寄存器有效时钟沿之前至少Tsetup时间,数据必须到达且稳定。如下图所示。


     保持时间要求:在数据采集有效时钟沿之后,数据必须维持最短Thold时间不变。如下图所示。


      建立时间裕量计算
同步时序电路如下图所示。这里对后面一个寄存器进行建立时间裕量分析。


     其中寄存器的输出延时为Tcq,即时钟有效沿之后延时Tcq时间,数据才到达寄存器Q端。第一个寄存器有效时钟沿之后Tcq时间,数据才到达Q1端,如下图所示。


     再经过组合逻辑运算,得到数据C1,其中组合逻辑的延时为Tlogic。时序如下图。


      从这里可以看到,如果clk2和clk1之间没有延时。那么对于后面的寄存器而言,数据提前于采样时钟沿之前Tcycle-(Tcq+Tlogic)时间到来,且稳定。其中Tcycle为时钟周期。


     由于寄存器要求的建立时间为Tsetup,故电路必须满足 Tcycle -(Tcq+Tlogic)- Tsetup>0 。建立时间裕量 Tset_slack = Tcycle -(Tcq+Tlogic)- Tsetup

如果clk1与clk2之间存在skew,如下图所示,如正skew。得建立时间裕量为

Tset_slack = Tcycle -(Tcq+Tlogic)- Tsetup + Tskew

这是对建立时间有益的。


    保持时间裕量计算
在时钟没有skew的情况下。在后一个寄存器有效采样时钟沿之后,同时新的C1只有经过Tcq+Tlogic之后才会到达。故要满足保持时间要求,只需要满足Tcq+Tlogic>Thold。保持时间裕量Thold_slack = Tcq+Tlogic-Thold


如果clk1与clk2之间存在skew。如下图所示(正skew)。


可以看到,C1_NEW在clk2时钟沿后,Tlogic+Tcq-Tskew就改变了。此时保持时间裕量Thold_slack = Tcq+Tlogic-Thold - Tskew 。可以看到,正skew对保持时间是无益的。

总结
可以看到,必须满足建立时间要求和保持时间要求,级满足如下关系式。

Tset_slack = Tcycle -(Tcq+Tlogic)- Tsetup + Tskew>0

Thold_slack = Tcq+Tlogic-Thold - Tskew > 0

从中可以看出,建立时间与保持时间要求是一对矛盾的关系,在设计电路时,我们要折中考虑。

Maggie • 来自相关话题

4月前

UVM验证平台中的常用机制(总结&概述)

    一个完整的UVM验证平台应该具有一些基本功能:产生并驱动激励,与DUT行为一致的理想参考模型reference_model(golden_model),监测并收集DUT和reference_mode的输入/输出信号,比较并判断DUV ...查看全部

    一个完整的UVM验证平台应该具有一些基本功能:产生并驱动激励,与DUT行为一致的理想参考模型reference_model(golden_model),监测并收集DUT和reference_mode的输入/输出信号,比较并判断DUV和reference_mode的输出是否一致且符合预期结果,等。这些基本的功能由相应的组件来完成。那么,这些组件之间是如何可靠、高效的完成验证工作的?或者说,UVM方法学中有哪些特有的机制可以保证验证平台自动的、可靠的并且高效率的完成验证工作呢?这篇内容将对一些常见的UVM机制进行一些简单的总结。
    常见的UVM机制:
    1.field_automation机制
    对field_automation最直观的感受是,他可以自动实现copy、compare、print等三个函数。当使用uvm_field系列相关宏注册之后,可以直接调用以上三个函数,而无需自己定义。这极大的简化了验证平台的搭建,尤其是简化了driver和monitor,提高了效率。    
    2.config_db机制
    config_db机制在UVM验证平台中主要用于参数传递。它们通常都是成对出现的,set函数是寄信,而get函数是收信。函数格式如下:
    uvm_config_db# (Type)::set(this,"inst_path","field",value); //将value寄送给 “field(字段)”
    uvm_config_db# (Type)::get(this,"","field",field)      //field将接收参数的传递
    结果得到:field = value;    
    所谓“字段”,是变量名包含的内容。在set和get函数中为第三个参数,字段在set和get中必须保持一致,才能保证参数的正确传递。例如要将参数值10,传递给int类型的变量data,则:
    uvm_config_db# (int)::set(this,"env.i_agt.drv","dat",10); //将10寄送给env组件中的成员变量“data”
    uvm_config_db# (int)::get(this,"","dat",data)      //字段“dat”保持一致,成员变量data将接收参数的传递
    结果得到:data = 10;    
    3.objection机制
    UVM中通过objection机制来控制验证平台的关闭,需要在drop_objection之前先raise_objection。验证在进入到某一phase时,UVM会收集此phase提出的所有objection,并且实时监测所有objection是否已经被撤销了,当发现所有都已经撤销后,那么就会关闭此phase,开始进入下一个phase。当所有的phase都执行完毕后,就会调用$finish来将整个验证平台关掉。如果UVM发现此phase没有提起任何objection,那么将会直接跳转到下一个phase中。
    UVM的设计哲学就是全部由sequence来控制激励生成,因此一般情况下只在sequence中控制objection。另外还需注意的是,raise_objection语句必须在main_phase中第一个消耗仿真时间的语句之前。
    4.factory机制
    factory机制的优势在于其具有重载功能。重载并不是factory机制的发明,只是factory机制的重载与这些重载都不一样。要想使用factory机制的重载功能,必须满足以下要求:
    1) 无论是重载的类(parrot)还是被重载的类(bird),都要在定义时注册到factory机制中。
    2) 被重载的类(bird)在实例化时,要使用factory机制的方式进行实例化,而不能使用传统的new的方式。
    3) 最重要的是,重载的类(parrot)要与被重载的类(bird)有派生关系。重载的类必须派生自被重载的类,被重载的类必须是重载类的父类。
    4) component与object之间互相不能重载。虽然uvm_component是派生自uvm_object,但是这两者根本不能重载。因为,从两者的new参数的函数就可以看出来,二者互相重载时,多出来的一个parent参数会使factory机制无所适从。
    当然,factory机制的实现被集成在了一个宏中:uvm_component_utils。这个宏最主要的任务是,将字符串登记在UVM内部的一张表中,这张表是factory功能实现的基础。只要在定义一个新的类时使用这个宏,就相当于把这个类注册到了这张表中。这样,factory机制可以实现:根据一个字符串自动创建一个类的实例,并且调用其中的函数(function)和任务(task),这个类的main_phase就会被自动调用。
    5.callback机制
    在UVM验证平台中,callback机制最大的用处就是提高验证平台的可重用性。很多情况下,验证人员期望在一个项目中开发的验证平台能够用于另外一个项目。但是,通常来说,完全的重用是比较难实现的,两个不同的项目之间或多或少会有一些差异。如果把两个项目不同的地方使用callback函数来做,而把相同的地方写成一个完整的env,这样重用时,只要改变相关的callback函数,env可完全的重用。
    除了提高可重用性外,callback机制还用于构建异常的测试用例,VMM用户会非常熟悉这一点。只是在UVM中,构建异常的测试用例有很多种方式,如factory机制重载,而callback机制只是其中的一种。
    6.phase机制
    在不同的时间做不同的事情,这就是UVM中phase的设计哲学。但是仅仅划分成phase是不够的,phase的自动执行功能才极大方便了用户。当new语句执行完成后,后边的connect语句肯定就会自动执行。现引入phase概念,将前面的new的部分包裹进build_phase里面,把后边的connect语句包裹进connect_phase里边,很自然的,当build_phase执行结束后就应该自动执行connect_phase。
    phase的引入在很大程度上解决了因代码顺序杂乱可能会引起的问题。遵循UVM的代码顺序划分原则(如build_phase做例化工作,connect_phase做连接工作等),可以在很大程度上减少验证平台开发者的工作量,使其从一段杂乱的工作中解脱出来。
    UVM中的phase按照其是否消耗仿真时间($time打印出的时间)的特性,可以分成两大类:一类是function_phase,如产生build_phase、connect_phase等,这些phase都不消耗仿真时间,通过函数来实现;另一类是task_phase,如run_phase等,他们消耗仿真时间,通过任务来实现。给DUT施加激励、监测DUT的输出都是在这些phase中完成的。
    所有的phase按照以下顺序自上而下自动执行:
    build_pase
    connect_phase
    end_of_elaboration_phase
    start_of_simulation_phase
    *run_pase*
    extract_phase
    check_phase
    report_phase
    final_phase

    其中,*run_phase*按照以下顺序自上而下执行:
    pre_reset_phase
    reset_phase
    post_reset_phase
    pre_configure_phase
    configure_phase
    post_configure_phase
    pre_main_phase
    main_phase
    post_main_phase
    pre_shutdown_phase
    shutdown_phase
    post_shutdown_phase

    7.sequence机制
    sequence机制用于产生激励,它是UVM中最重要的机制之一。sequence机制有两大组成部分:sequence和sequencer。在整个验证平台中sequence处于一个比较特殊的位置。sequence不属于验证平台的任何一部分,但是它与sequencer之间有着密切的关系。只有在sequencer的帮助下,sequence产生的transaction才能最终送给driver;同样,sequencer只有在sequence出现的情况下才能体现出其价值,如果没有sequence,sequencer几乎没有任何作用。除此之外,sequence与sequencer还有显著的区别。从本质上说,sequencer是一个uvm_component,而sequence是一个uvm_object。与my_transaction一样,sequence也有其生命周期。它的生命周期比my_transaction要更长一点,其内部的transaction全部发送完毕后,它的生命周期也就结束了。
    8.通信机制TLM1.0
    UVM中,通常使用TLM(Transaction Level Modeling)实现component之间transaction级别的通信。TLM现在已经发展到TLM2.0,是对TLM1.0的扩展。但是TLM1.0足以满足大多数完整的验证平台的通信要求,所以主要学习TLM1.0。关于TLM1.0通信机制,后续将会详细介绍。