UVM细碎知识点

  1. 【15-UVM入门进阶2.P58】uvm_config_db遵循“先配置后例化”。
    (1) SV里只能先例化对象,然后才能利用例化对象的层次化索引去传递变量/接口;而UVM里因为有了config_db机制,我们可以根据实际需求先把各层次类class的变量/接口get后丢到config_db的箱子里,各层次类class再去这个箱子对变量/接口set设置具体的value,进而达到“先配置再例化”的定制化。
    (2) 【九大phase执行顺序】① 0时刻前,编译与链接(config_db在此时配置???);② 0时刻,always/initial块→调用顶层initial的run_test()→执行全局build_phase等4个phase;③ run时,执行run_phase;④ run后,执行extract_phase等4个phase。 phase机制4-1-4
    (3) 先顶层set再底层get,然后build_phase里的comp1::type_id::create(),最后run_test()。
  2. 【UVM实验0】几个sv都是module模块里放着initial,只要compile→nonvopt→run -all,就能够执行initial里的内容。(难道因为module是硬件模块,所以run后就直接initial了?)
  3. 【UVM实验0】uvm_test_inst.sv的initial语块里的run_test(“top”)可以直接执行top这个类(class)!前提是包含该initial的module先import包含top类的test_pkg :: *。
  4. 【UVM实验0】只有继承于uvm_test的类,才有资格作为UVM验证环境的顶层。
  5. 【UVM实验1】vsim -novopt -classdebug +UVM_TESTNAME=object_create work.factory_mechanism
    work.factory_mechanism中的factory_mechanism是factory_mechanism_ref.sv中的模块名。
  6. 【UVM实验2】run_phase()里不用调用子一级的run,因为子一级的run本来就会有run_phase()去调用执行。例如:chnl_pkg.sv→class chnl_agent→task run_phase(),对比reg_pkg.sv→class reg_driver→task run_phase()。如下代码:
  class chnl_agent extends uvm_agent;
  	...
    task run_phase(uvm_phase phase);
      // fork
      //   driver.run();
      //   monitor.run();
      // join
      // HINT:: 没有必要再手动调用子一级的run了,即driver.run()和monitor.run()
      // 首先,uvm_root在compile之后就存在了(id:@1),即run前就有了,run_test()相当于唤醒调用它
      // 其次,uvm_root()作为上帝,掌握所有层次的关系hier,但是不像SV那样“点火”由顶至下执行run(),
      // 而是用fork...join_none让所有层次的run_phase()在同一时刻被执行
      // 即遍历所有组件的run_phase()/将各个组件的run_phase()独立地调用一遍,
      // 就能拿到每个run_phase()的句柄
    endtask
  endclass: chnl_agent

uvm_root是创世主@1

  1. 【11-SV语言五】initial语块会等待fork…join结束完再退出仿真,但是路科说不会等待fork…join_any和fork…join_none执行完再退出仿真。通过QuestaSim仿真,发现initial语块同样会等待fork…join_any和fork…join_none执行完再退出仿真。
module initial_fork_join_none_order;
  initial begin
    $display("@%0t: module starts", $time()); 
    #10 $display("@%0t: after #10", $time());
    fork
      begin
        #20 $display("@%0t: fork...join_none after #20", $time());
      end
    join_none
    $display("@%0t: after fork...join_none", $time()); 
  end
endmodule: initial_fork_join_none_order

QuestaSim仿真结果

  1. 【19-UVM入门进阶6-P35】如何让客户拓展封闭的包(如商用VIP)?① 通过类的继承+UVM的override机制;② 在VIP中某个class的某个方法func的前后预留方法接口,利用callback回调函数,在该方法func前后预留pre_callback()和post_callback(),可以配合external使用。
  2. 【UVM入门进阶实验3】如何在DVT eclipse里查看树状层次结构,QuestaSim的class instances实在不好用。
    DVT查看树状层次的步骤
  3. 【UVM入门进阶6-视频7】TLM (Transaction Level Modeling)相对于mailbox的优势:
    (1)TLM除了具有mailbox的缓存功能外,还可以在一对多情况下initiator端用uvm_analysis_port/export/imp的方式去轮询target端内置的write()函数,通过其返回值去触发其他event;
    (2)TLM具有观察者模式(observer pattern)或叫广播模式,支持一对多的put,也可以允许“空发”,即get的imp数量为0,但是mailbox的REQ和RSP句柄只能成对出现,尽量要避免空句柄的现象;
    (3)在单端对单端的传输方式中,mailbox是利用层次化索引进行,各组件之间耦合较多,而TLM通过port/export/imp端口作中介,降低了各组件之间的粘度。
  4. 【20-UVM入门进阶7-P11】driver是initiator,sequencer是target,driver采用get模式(而不是put模式),有以下考虑:
    (1)如果是get模式,传输路径很通畅,即sequence item (from sequence)→sequencer→driver,效率很高;如果是put模式,sequencer发起put后,还需等待driver返回rsp允许发送,才能传输数据,效率低;
    (2)sequencer拥有仲裁特性,即允许多个sequence同时挂载到sequencer上。通过driver的get模式,sequencer只需要专注于仲裁,driver作为initiator只需要发出get请求,就可以通过sequencer拿到仲裁后的sequence item。
  5. 【20-UVM入门进阶7-P18】sequence挂载到sequencer上后,sequence就会自动执行body(),不用手动执行,类似于组件类的run_phase()。
  6. 【 20-UVM入门进阶7】小白第一年:(1)写sequence;(2)写test???【测试场景都放在sequence里写,test只是执行顶层virtual sequence的挂载并执行】。
  7. 【20-UVM入门进阶7-P18】虚拟类(virtual sequence)
  8. 【UVM实验4】driver里(包括chnl_pkg、fmt_pkg、reg_pkg)都是用的seq_item_port去get_next_item(req)和item_done(rsp),虽然名字一样都叫seq_item_port,但是由于有connect_phase,可以通过层次索引将需要握手的双方连接在一起,如下图:
    各个pkg的driver里mailbox转seq_item_port的用法
  9. 【UVM实验4-reg_pkg_reg.sv】
    ① uvm_sequence_item类:包括rand型变量、constraint约束条件、field automation域自动化声明、new;
    ② uvm_sequence #(Type)类:Type如uvm_sequence_item类的子类reg_trans,包括rand型变量(赋值-1)、constraint约束条件(赋值-1)、field automation域自动化声明、宏uvm_declare_p_sequencer(放要挂载的sequencer)、body()【含uvm_sequence_item类的变量、`uvm_do_with(var, cstr)、可选项get_response()、其他握手传参的操作】;
    ③ uvm_sequencer #(Type)类:Type如uvm_sequence_item类的子类reg_trans,只需extends→utils注册→new创建;
    ④ uvm_driver #(Type)类:Type如uvm_sequence_item类的子类reg_trans,包括set_interface()【含有层次化包含的地方就会有set_interface(),如uvm_monitor,但是uvm_sequencer没有,它只需要通过TLM与uvm_driver子类通信即可,如driver.seq_item_port.connect(sequencer.seq_item_export); 】、run_phase()【需要run()的地方就会有run_phase(),如uvm_monitor】。
  10. 【UVM实验4-reg_讲解1】UVM预定义函数create_item()在定义时就已经是uvm_sequence_item类(即父类),所以tmp在调用时,就是父类句柄(uvm_sequence_item)指向子类对象(bus_trans),因此每次create_item()都要$cast转化。
    create_item的用法
protected function uvm_sequence_item create_item
	(
		uvm_object_wrapper type_var,
		uvm_sequencer_base l_sequencer,
		string name
	);

	uvm_coreservice_t cs = uvm_coreservice_t::get();
	uvm_factory factory=cs.get_factory();
	$cast(create_item, factory.create_object_by_type( type_var, this.get_full_name(), name ));

	create_item.set_item_context(this, l_sequencer);
endfunction
  1. 【136-寄存器模型的常规方法1.mp4】00:00:10 详细介绍了register_model和reg_agent、DUT的交互过程,包括RGM里map产生uvm_reg_op类的reg,到adapter里通过reg2bus函数转化变成bus_trans,传输给reg_agent里的sequencer→driver,最后从interface给到DUT,当然还有bus2reg函数、predictor、auto_predict等细节。
  2. 【23-UVM入门进阶10】对Register Model寄存器模型的深入理解:desired value是用来先更新软件侧model对象的值,再利用该值更新硬件侧的actual value,紧接着通过bus2reg的adapter去更新软件测model的mirror value。desired value、actual value、mirror value都存放在各个uvm_reg_fielld子类里,uvm_reg_field是各个value的最小存放单元。
  3. 【26-UVM项目实战3】
    (1)断言(assertion)不能修改设计行为,分为:
    ① 立即断言(immediate assertion):非时序,如:assert (y==0) else flag=1;
    ②并行断言(concurrent assertion):时序性的、带关键词property、与设计模块一起并行执行,如:
    property req_grant_prop
    	@(posedge clk) req ##2 gnt ##1 !req ##0 !gnt;
    endproperty
    assert property req_grant_prop else $error ("Req Grant Protocal Violation");
    
    并行断言必须要有时钟,功能类似于clocking块,可以采样得到稳定的设计信号变量,避免竞争。
    (2)sequence是用来表示在一个或多个时钟周期内的时序描述(但却与uvm_sequence无关); 是property的基本构建模块,并经过组合来描述复杂的功能属性。
    property块可以直接包含sequence,复杂的property块也可以独立声明多个sequence。
    sequence s1;
    	@(posedge clk) a ##1 b ##1 c;
    endsequence
    sequence s2;
    	@(posedge clk) a ##1 c;
    endsequence
    property p1;
    	@(posedge clk) disable iff (!reset)
    	s1 |=> s2;
    endproperty
    
    sequence不能在class里声明(在module、interface、program、clocking块、package都可以),assert property不能在class里声明。
    ==>建议:assertion只放在interface里声明!!!
    (3)蕴含(implication)操作符:如果property中左边的先行算子成立,那么property右边的后续算子才会被计算,分为::“成功”、“空成功”、“失败”三种情况。
    ① 交叠蕴含操作符|->:左边算子成立后,当前周期就执行右边算子;
    property p_req_ack;
    	@(posedge clk) mem_en |-> (req ##2 ack);
    endproperty: p_req_ack
    
    ② 非交叠蕴含操作符|=>:左边算子成立后,下一周期才执行右边算子。
    property p_req_ack;
    	@(posedge clk) mem_en |=> (req ##2 ack);
    endproperty: p_req_ack
    
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值