UVM面试问题小结

1.试描述你对UVM的理解。(突出你自己的理解)
以 sv语言为基础搭建验证平台框架,利用可重用的组件构建标准化层次结构和接口的验证环境,uvm类似于Python里面的类库,可以调用里面的函数/修改框架结构。
system verilog主要适用于模块级/IP级验证,与上层衔接度没有uvm好,uvm是一个分层的测试平台,看起来比较复杂,但是把代码分而治之,比如里面有一些思想有sequence机制,之前sv的driver负责数据的转换,发送等,现在有了sequence_item(水,子弹),sequence(蓄水池,弹夹),squencer(调度站,手枪),driver(总工厂,扣动扳机),拆分了任务,工作相互独立又存在联系,快速搭建一个需要的测试平台,会在大型验证中减轻工作负担,重复利用率提升。

2.UVM的相关的类有哪些,简单列出来,并说明uvm_object和uvm_component的联系和区别。
uvm_object,uvm_transaction, uvm_sequence_item, uvm_compoent,uvm_driver,uvm_monitor,uvm_agent,uvm_scoreboard,uvn_env,uvm_test,uvm_root

联系:uvm_component继承自uvm_object,uvm_component拥有uvm_object的特性。
区别:uvm_component有两大特性是uvm_object所没有的,一是通过在new的时候指定parent参数来形成一种树形的组织结构,二是有phase机制的自动执行特点。
需要component这种复杂类进行TB层次化搭建,也需要object基础类进行TB的事务搭建和环境配置。

3.UVM的树形结构;(自己画出来)
每个测试用例建立的UVM树形结构
UVM面试问题小结_第1张图片
import uvm_pkg:: *;
导入uvm_pkg文件包时,会自动创建一个顶层类uvm_root所例化的对象,即uvm_top
uvm_root顶层类会提供run_test()方法,通过uvm_top调用方法run_test(test_name)做如下初始化:
1.得到正确的test_name;
2.初始化objection机制;
3.创建uvm_test_top实例;
4.调用phase控制方法,安排所有的phase方法执行顺序;
5.等待所有的phase执行结束,关闭phase控制进程;
6.报告总结和仿真结束

4.简述UVM的phase机制,function phase和task phase分别起什么作用。树型结构中如何运行的?
sv对象例化构建new()函数,存在一个重要问题就是如何保证例化的先后关系,以及组件例化后的连接;
phase机制使得uvm的运行仿真层次化,不仅使得各个phase的先后执行顺序正确, 处于同一phase层次化组件之间的phase也有先后。

首先要创建各个组件的对象,所以最先执行的就是build_phase,只有先创建高层次的组件才会有空间来容纳低层次的组件,所以它的执行顺序是自顶向下的;然后要进行各个组件的连接,所以执行connect_phase,首先要进行底层组件的连接,所以它的执行顺序是自底向上的;build time phase的后两种phase基本不会用到,主要用来显示UVM的层次结构信息;测试激励在run_phase被发送到DUT中,run_phase和其他run time phase之间都是并行的,细分的12个phase是先后顺序,一般避免执行关系混乱不会混用run phase和12个phase;
run_phase中完成测试需要按照下面的激励序列:
1.上电;2.复位;3.寄存器配置;4.发送主要测试内容;5.等待dut完成测试
UVM面试问题小结_第2张图片
下面是各个phase的执行顺序和功能
UVM面试问题小结_第3张图片
常用的phase包括build,connect,run,report,分别是组件的创建,连接,运行,报告。
树形结构中如何运行呢? UVM面试问题小结_第4张图片在加载硬件模型调用仿真器之前,要完成编译和建模阶段;

在仿真开始之前,分别执行硬件的always/initial语句,以及UVM的调用测试方法run_test()和几个phase,顶层调用全局函数run_test(),run_test()函数可以在合适的module中的initial过程快中调用,也可以在仿真时候传递参数+UVM_TESTNAME=来选择test;分别是build_phase、connect_phase、end_of_elaboration_phase、start_of_simulation_phase;

在仿真开始后,执行run_phase或对应的12个细分的phase;利用 objection挂起机制来控制仿真结束。run阶段至少有一个组件要把objecttion(component和sequence共享计数器)挂起,防止run phase 退出,如果没有挂起uvm就会立即退出 run phase;

在仿真结束后,执行剩余的phase,分别是extract_phase、check_phase、report_phase、final_phase;

5.简述UVM的TLM通信机制,在各个component之间是如何连接的。
TLM(transaction level modeling)是一个基于事务(transaction)的通信方式,通常使用tlm 来作为不同component之间的数据传递和通信。
UVM面试问题小结_第5张图片

initiator 例化发起端port(调用connect函数),中间层次例化export,target例化imp端口(作为connect参数);组件1.port.connect(组件4.export)
多port对应一export或者imp(多个initiator可对同一target发起request),单个port或者export不能连接多个imp(同一initiator无法连接多个target);
扩展性:port可以连接port,export或者imp;export可以连接export或者imp,imp作为数据终点,无法拓展连接

class request extends uvm_transaction;
    byte cmd;
    int  addr;
    int  req;
endclass

class response extends uvm_transaction;
    byte cmd;
    int  addr;
    int  rsp;
    int  status;
endclass

class comp1 extends uvm_agent;
    uvm_blocking_get_port #(request) bg_port;
    `uvm_component_utils(comp1)
    ...
endclass

class comp2 extends uvm_agent;
    uvm_blocking_get_port #(request) bg_port;
    uvm_nonblockign_put_imp #(request, comp2) nbq_imp;
    `uvm_component_utils(comp2)
    ...
    function bit try_put(request req);
    functuin bit can_put();
class

class comp3 extends uvm_agent;
    uvm_blocking_transport_port #(request, response) bt_port;
    `uvm_component_utils(comp3);
    ...
endclass

class comp4 extends uvm_agent;
    uvm_blocking_get_imp #(request, comp4) bg_imp;
    uvm_nonblocking_put_port #(request) nbp_port;
    `uvm_component_utils(comp4);
    ...
    task get(output request req);
endclass

class comp5 extends uvm_agent;
    uvm_blocking_transport_imp #(request, response, comp5) bt_imp;
    `uvm_component_utils(comp5);
    ...
    task transport(request req, output response rsp);
endclass

class agent1 extends uvm_agent;
    uvm_blocking_get_port #(request) bg_port;
    uvm_nonblocking_put_export #(request) nbp_exp;
    uvm_blocking_transport_port #(request, response) bt_port;
    comp1 c1;
    comp2 c2;
    comp3 c3;
    `uvm_component_utils(agent1)
    ...
    function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        c1 = comp1::type_id::create("c1", this);
        c2 = comp2::type_id::create("c2", this);
        c3 = comp3::type_id::create("c3", this);
    endfunction
    
    function void connect_phase(uvm_phase phase);
        super.connect_phase(phase);
        c1.bg_port.connect(this.bg_port);//connect左侧可以是port、export,右侧是imp
        c2.bg_port.connect(this.bg_port);
        this.nbp_exp.connect(c2.nbp_imp); //连接方向从agent的export到c2的import
        c3.bg_port.connect(this.bg_port);
    endfunction
endclass

class env1 extends uvm_env;
    agent a1;        
    comp4 c4;
    comp5 c5;
    `uvm_component_utils(env1)
    ...
    function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        a1 = agent::type_id::create("a1", this);
        c4 = comp4::type_id:;create("c4", this);
        c5 = comp5::type_id:;create("c5", this);
    endfunction

    function void connect_phase(uvm_phase phase);
        super.connect_phase(phase);
        a1.bg_port.connect(c4.bg_imp); //a1的port接口与c4的imp接口连接
        c4.nbp_port.connect(a1.nbp_exp); //c4的port接口与a1的export接口连接
        a1.bt_port.connect(c5.bt_imp); //a1的port接口与c5的imp接口连接
    endfunction    
endclass

端口调用前几个步骤:定义端口;实现对接方法;在上层将端口进行连接

UVM面试问题小结_第6张图片

6.简述UVM的sequence、driver、sequencer之间的关系。
UVM面试问题小结_第7张图片
产生:
sequence(道路):产生激励内容的载体,最小粒度是sequence item(货车)
自驾item–uvm_sequence_item类:激励所需要的具体数据和控制要求;
大巴sequence–uvm_sequence类:激励生成和场景控制;

驱动
sequencer(目的地的关卡):通过TLM端口与driver传动item对象,面对多个sequence时候,充分的仲裁机制合理分配和传送item;两件事:检测仲裁队列里是否有某个sequence发送tansaction请求,检测driver是否申请transaction;

driver(卸货地方):消化完一个sequence ,报告sequencer,请求下一个item,把item中数据按照与dut的物理协议时序关系驱动到接口上面;

7.Sequence和case是如何联系起来,并且发送出去的。
1:sequence创建sequence_item,随机化方法产生一个trans,且每个trans各不相同
2:sequence 请求发送,准备好trans后,向sequencer作申请要发送
3 :sequencer 仲裁,选择发送哪个sequence的trans
4:sequence等待driver的peek数据流请求[没有调度通过的sequence将一直阻塞在这里,直到仲裁通过
;如果driver早就发送了peek请求并阻塞在这,sequencer在调度完之后就会立即发送。注意是peek请求,sequencer会自己保留一份]
5.sequence将trans发送给driver,通过sequencer与driver建立的TLM的端口通信实现的
6.sequence等待driver的反馈,driver获得trans之后向sequencer通过TLM反馈收到数据了。之后为仲裁通过sequence继续参与新一轮仲裁,返回上面第三步
UVM面试问题小结_第8张图片
sequence产生trans有四种方法:1.使用uvm_do宏 2.使用uvm_rand_send宏 3.使用uvm_create和uvm_send宏 4.使用start_item和finish_item
当sequencer发送给driver时,会自己留存一份,直到收到driver返回的item_done时才将其删除。

sequence的启动(挂载)方式:
1.显式启动,通过在env或者sequencer中调用自身的start函数。
2.隐式启动,使用default_sequence(config_db)。

//sequence的显式启动
//该方法提起和落下objection,通过phase.raise_objection(this)/phase.drop_objection(this)
my_sequence   seq = my_sequence::type_id::create("seq");
phase.raise_objection(this);
seq.start(sequencer);
phase.drop_objection(this)

//在my_sequence中的body任务中
virtual task body;
  if(starting_phase != null)
    starting_phase.raise_objection(this);
  repeat(10)begin
    `uvm_do(req);
  end
  if(starting_phase != null)
    starting_phase.drop_objection(this);
endtask

//sequence的隐式启动
//该方法可以在sequence中使用starting_phase提起和撤销objection
uvm_config_db#(uvm_object_wrapper)::set(this,"env.i_agt.sqr.main_phase",
                                        "default_sequence",
                                         case0_sequence::get_type());

uvm_do系列宏封装了从transaction实例化到发送的一系列操作(将start_item与finish_item动作封装)

一个激励从产生直到结束流程UVM面试问题小结_第9张图片UVM面试问题小结_第10张图片

8.简述run_test()函数的机制。

UVM验证平台从仿真器执行时,开始执行initial中的run_test(); 这时首先去uvm_global.svh中查找run_test();
全局的run_test() 又调用uvm_root.svh的run_test(),传入test_name的名字
在该run_test 实现中根据有没有DPI调用phase.这样在运行仿真命令时通过simcmd +UVM_TESTNAME=my_case 来执行该case,这样整个系统就被调用了起来。这样做有什么好处?它根据传入的字符串或者从运行参数+UVM_TESTNAME="test_name"读取字符串生成uvm_test对象, 并运行这个对象的全部phase函数来执行一次测试用例的运行,很方便实现regression。

转载于:https://www.cnblogs.com/dpc525/p/7859704.html

你可能感兴趣的:(UVM,学习,stm32)