UVM知识点总结

UVM知识点总结

Tags: protocol

当UVM启动后, 会自动执行build_phase(仿真0时刻)UVM通过run_test语句实例化了一个脱离了top_tb层次结构的实例, 建立了一个新的层次结构在UVM验证平台中, 只要一个类使用uvm_component_utils注册且此类被实例化了, 那么这个类的main_phase就会自动被调用在每个phase中, UVM会检查是否有objection被提起 ( raise_objection) , 如果有, 那么等待这个objection被撤销( drop_objection) 后停止仿真; 如果没有, 则马上结束当前phase。模拟的数据包,是有生命周期,仿真的某一时间产生,并于check对比后结束

  • 验证平台中所有的组件均应派生自UVM中的类。

  • factory机制:必须用宏 uvm_component_utils,uvm_object_utils, uvm_object_utils_begin … end 注册后才能使用。

  • UVM factory机制会维护一个注册表,这些宏可以把用户定义的类注册到该表中。

  • 在uvm_top中使用run_test(“your_test_name”),它会自动创建和运行类,该对象的名字是uvm_test_top。也可以在run的命令行中添加:+UVM_TESTNAME=my_case 来指定运行某个case。

  • config_db 机制:由于UVM通过run_test语句实例化了一个脱离了top tb层次结构的实例,建立了脱离了硬件世界的软件天地,为了对这片天地里的信号等进行配置,UVM引入了config_db机制。

  • config_db分为set和get两部操作。

  • 在main_phase中,raise_objection() 应该放在第一个消耗时间的语句前,否则无法起到作用。当然,标准的基于uvm 的testbench只应该在sequence里 raise/drop objection.

  • 在build_phase时是从树根到叶子,有在每级节点创建完成后才开始下级结点的创建。同一级下的component创建先后顺序不确定。在connect_phase时是从叶子到树根的顺序.

  • interface在class中使用会引起编译错误。为了在class中使用,SystemVerilog创造了virtual interface。

  • 使用UVM宏语句的结尾不用分号结尾也可,如 uvm_info, uvm_fatal, uvm_component_utils 等。

  • UVM test类的三个主要作用:例化顶层验证环境 2.通过factory overrides或config db的方式配置验证环境 3.通过引入Sequence来完成test的具体测试内容。

  • UVM env类: 一个soc top env下可能由许多 dedicated的env,如PCIe Env, USB env, Memory controller Env等。

  • filed automation机制: 提供copy(),compare(),print()等函数,以及pack_bytes(),unpack_bytes()等。

  • pack_bytes(data_q)将tr中所有的字段变成byte流放入data_q中,其放入顺序是根据uvm_filed系列宏的书写顺序排列的。

  • unpack_bytes(data_array) 函数将data_array数组中的byte流转化成tr中已被filed automation注册过的各个字段

  • 在定义component 时使用参数化的定义之名使用的transcation类型,这样可以使用其预定义好的成员变量,如driver中的req

  • sequence不属于验证平台的任何一部分。sequence就像弹夹,里面的子弹是transcation,而sqeuencer是一把枪。弹夹用完就扔掉没用了,但枪只有战斗结束才不用。

  • uvm_macros.svh文件通过include语句包含进来。 这是UVM中的一个文件, 里面包含了众多的宏定义, 只需要包含一次。

  • import语句将整个uvm_pkg导入验证平台中。 只有导入了这个库, 编译器在编译my_driver.sv文件时才会认识其中的uvm_driver等类名。

  • 注意事项:在UVM定义中,组件或者object的注册都应该放在变量的声明之后。

  • 注意事项:uvm_driver中有成员变量seq_item_port, 而在uvm_sequencer中有成员变量seq_item_export, 这两者之间可以建立一个“通道”, 通道中传递的transaction类型就是定义my_sequencer和my_driver时指定的transaction类型。

  • 注意事项:uvm_top是一个全局变量,可以直接使用uvm_top。它是uvm_root的一个实例,得到它的指针:top=uvm_root::get()

  • uvm_do宏做如下事:

    • 创建一个transcation的实例。
    • 将其随机化。
    • 最终将其送给sequencer。
    • driver从sequencer中获取item的方法:
    • get_next_item(req)是阻塞的
    • try_next_item(req)是非阻塞的
    • try_next_item的行为更接近真实的driver的行为,当由数据时就驱动数据到总线,否则总线就处于空闲状态。
    • 通过set default_sequence的方式启动sequence。
    • starting_phase是uvm_sequence基类中的uvm_phase类型的成员变量。sequencer在启动default_sequence时,会将自身的phase赋值给starting_phase. 因此sequence中可以使用starting_phase进行raise/drop objection。
  • uvm_transaction和uvm_sequence_item有什么区别?

    • uvm_transaction是从uvm_object派生的用于对事务进行建模的基类。
    • sequence item是在uvm_transaction的基础上还添加了一些其他信息的类,例如:sequence id。建议使用uvm_sequence_item实现基于sequence的激励
  • sequencer和driver之间的握手协议

    在sequence端:

    1. start_item():请求sequencer访问driver
    2. finish_item():使driver接收sequence item,这是阻塞调用,在driver调用item_done()方法后才返回。

    在driver端:

    1. get_next_item(req):这是driver中的一个阻塞方法,直到接收到sequence item,driver可以将其转换为引脚级协议信号。
    2. item_done(req):向sequencer发出信号,表明它可以接受新的sequence请求,使得sequence解除对finish_item()方法的阻塞。
  • backdoor和frontdoor访问有什么区别?

    backdoor访问:通过RTL信号路径访问,不消耗仿真时间

    frontdoor访问:通过数据总线协议访问,消耗仿真时间

  • Phase的运行

    所有不耗费仿真时间的phase( 即function phase) 都是自下而上执行的,按照层次结构,同一层次的兄弟结构按照字典序的顺序执行。
    对于不同的component,同一个run_phase(或reset_phase)是自下而上的启动,同时运行。
    对于同一component来说, 其12个run-time的phase是顺序执行的。即对于每个component来说,总体12个小的run_phase之间可能会有间隔,但是对于,系统来说,所有component的12个小run_phase是顺序,无间隔的执行完毕。

  • 不能直接把my_monitor中的analysis_port和my_model中的blocking_get_port相连吗?需要一个fifo呢?

    因为AP的writer函数是非阻塞的,调用完后马上返回,需要一个缓冲来存储端口数据

  • transaction,sequencer与driver的区别?

    Transaction 继承与uvm_sequence_item类型,是object类型。模拟的是一个数据包,有生命周期,从产生开始到比较完毕结束。
    Driver接收transaction,负责把transaction级别的数据转变成DUT的端口级别, 并驱动给DUT,driver只负责驱动transaction, 而不负责产生transaction。uvm_driver也是一个参数化的类,其参数是定义的transaction类型,component类型
    Sequencer作为sequence与driver的桥梁,做仲裁,: 第一, 检测仲裁队列里是否有某个sequence发送transaction的请求;(start_item) 第二, 检测driver是否申请transaction。(get—next_item) 。uvm_sequencer是一个参数化的类,派生自uvm_sequencer。 其参数是my_transaction,component类型

    sequence不属于验证平台的任何一部分,object类型 ,也是一个参数化的类,其参数是定义的transaction类型,
    它与sequencer之间有密切的联系, 这点从二者的名字就可以看出来。 只有在sequencer的帮助下, sequence产生出的transaction才能最终送给driver; 同样, sequencer只有在sequence出现的情况下才能体现其价值, 如果没有sequence, sequencer就几乎没有任何作用。 sequence就像是一个弹夹, 里面的子弹是transaction, 而sequencer是一把枪。 弹夹只有放入枪中才有意义, 枪只有在放入弹夹后才能发挥威力。
    每一个sequence都有一个body任务, 当一个sequence启动之后, 会自动执行body中的代码。 在上面的例子中, 用到了一个全新的宏:uvm_do。[`uvm_do(m_trans)]它用于: ①创建一个my_transaction的实例m_trans; ②将其随机化; ③最终将其送给sequencer。

  • UVM工厂机制作用

    工厂的三大作用,注册,创建,重载

    1. 方便component类型生成树形结构
    2. 为object类型和component类型提供override功能
    3. 提供了对象的copy和clone,compare等方法
  • New()和type_id::creat的区别?在什么时候做?

    Type_id::creat会间接的调用new函数,在调用之前会检查目标类型是否被覆盖,
    Type_id::creat和new的创建不同不会影响到phase的运行,因为,如build和connect的执行和组建之间的层次关系有关,而层次关系的形成与组件的new()函数相关。两种方式都会调用new()函数

  • 联合数组是什么?

    联合数组是SystemVerilog中定义的一种非常有用的数据类型,在验证平台中经常使用。UVM对其提供了良好的支持,与联合数组相关的uvm_field宏有:
    define uvm_field_aa_int_string(ARG, FLAG) define uvm_field_aa_string_string(ARG, FLAG)
    define uvm_field_aa_object_string(ARG, FLAG) define uvm_field_aa_int_int(ARG, FLAG)
    ……
    联合数组有两大识别标志,一是存储数据的类型,二是索引的类型,
    在这一系列uvm_field系列宏中,出现的第一个类型是存储数据类型,第二个类型是索引类型,如uvm_field_aa_int_string用于声明那些存储的数据是int,而其索引是string类型的联合数组。

  • m_sequencer和p_sequencer有什么区别?

    m_sequencer和p_sequencer有什么区别?
    M_sequence 是uvm_sequence_item的成员变量,可理解为一个句炳,指向此sequence所挂载的sequencer。m_sequencer是uvm_sequencer_base类型,如果要访问my_sequencer的成员变量,需要做类型转化,将m_sequence转化为p_sequence。使用`uvm_declare_p_sequencer宏声明p_sequencer,实际做的事情就是声明了p_sequence并实现父类句柄转化为子类句柄

  • 5
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值