《UVM实战(卷1)》学习笔记_第1页
《UVM实战(卷1)》学习笔记_第2页
《UVM实战(卷1)》学习笔记_第3页
《UVM实战(卷1)》学习笔记_第4页
《UVM实战(卷1)》学习笔记_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、vrrtual t=uvn_fnorLtor and 1 ntt. I Al 17s irwstancft of this cIars ijr i ng the ncrnal / CDnsT.mctor arEiiiftflnts for : rkannft Is the nanA of TJhe / Inst.ancft, and parFsnl, Is Xhe handle Tm the hierarchical parentp IF any. f unctiari - leui tsLr iri narie. uvm. Campo rent parent ; supr . rituui

2、ridiie. partri L ; eridFunction const gtatic string type_nsr*ie virtusl PJi-i匚七丨口门 atirgp_name retjirn tij匚e_nairie endFuiri 亡 t 二 on cndclaEZ sequencer要派生自uvm_sequencer.sequencer做了很多扩展,但是如果我们自己写的sequencer里没有增加 -成员的话,可以直接写如下代码: typedefuvm_sequencer#(传递的 sequence_item 类名)sequencer 类名; 因为 seque ncer在

3、age nt中例化,所以一般写在agent类文件里。 reference_model 派生自 uvm_component. age nt要派生自uvm_age nt.uvm_age nt里多了一个is_active的成员。一般根据这个 active来决定是否实例化 driver和sequencer.is_active变量的数值需要在 env的build_phase里设置完成(可以直接设置,也可以用 uvm_config_db#(int):set )。 env 要派生自 uvm_env.uvm_env 没有对 uvm_component 扩展。 src/comps/uvm_e nv.svh 所有

4、的test都要派生自uvm_test或者它的派生类。uvm_test也没扩展 src/comps/uvm_test.svh uvm_object 禾口 uvm_component 的 macro macro非常重要,事关把这些类的对象注册到 factory机制中去。 uvm_objectmacro 、uvm_object_utils_begin(item 类名) vm_sequence,要fie上_automation uvmobjeputi 上述函数都是在 connect_phase及后面的phase使用 设置UVM_ERROR到达一定数量结束仿真 set_report_max_quit_c

5、ount(int) 设成 0 就是无论多少 error 者E不退出 get_report_max_quit_count()返回如果是0,说明无论多少 error都不退出 设置在main_phase前调用。 simv+UVM_MAX_QUIT_COUNT=10 344345346347我觉得应该用不大到,就不做笔记了 3.5config_db 机制 uvm_config_db#(类型):set/get(component 指针,”;变量名字 ”,para4) 都是4个参数: 第一个参数是一个 component指针,如果是 null的话,相当于 uvm_root:get() 第二个参数是个路径字

6、符串,第一和第二两个参数组和成一个完整的路径 第三个参数对于set、get要完全一致,是变量名字 set的para4是数值,get的para4是变量 component中的成员变量如果: 1) component 用 uvm_component_utils 宏注册 2) 变量用field-automation宏注册 3) component 的 build_phase 函数里有 super.build_phase(phase) 那么可以省略get语句 跨层次多重set的时候,看set的第一个参数,层级越高,优先级越高。 调用set的时候,第一个参数尽量使用 this 同层次设置的时候是时间优先

7、 非直线设置的时候注意第一和第二参数的使用,如果需要pare nt指针,则要用this.m_pare nt config_db机制支持通配符,但是作者不推荐使用通配符。但是在对sequenee的成员set的时候需要用通配符(6.6.1 章节)。 使用如下函数调试 con fig_db check_config_usage()print_config(1/0)这两个函数在 connect_phase 函数中调 simv+UVM_CONFIG_DB_TRACE 注意:第二个参数设置错误不会报错! config_db机制务必要注意参数的书写。 第4章UVM中的TLM1.0通信 TLM 是 Trans

8、actionLevelModeling 缩写 这章要搞清楚 portexportimpfifo 以及几种操作 function/task和对应component中要实现的function/task 下面的箭头方向都是控制流的方向,不是数据流方向。 我觉得作为一个 VMM用户会觉得TLM有点难理解,总想用 VMM_CHANNEL去套,结果把自己搞晕。像port等 其实是调 imp 所在 component 的 task/function. 我看 UVM 源代码里有一个 uvm_seq_item_pull_port 的 class,它的基类是 uvm_port_base.在 uvm_driver

9、的成员 seqtem_port 就是这个类型的。与它对应的是uvm_seqtem_pullmp , uvm_sequencer 的成员 seq_item_export 就是这种类型。在 my_agent.sv中会connect它们。 4.2端口互连 port是动作的发起者,export是动作接收者,但是需要以一个imp来结束。 可以 port export impport port imp 也可以 port impexport imp i I port imp用的较多,port port imp可以用port指针赋值来实现 port port(4.3.2章节) 操作: putget/peekt

10、ransport,transport 相当于一次 put+ 一次 get peek和get的不同(4.3.4章节):使用uvm_tlm_analysis_fifo的时候,get任务会使fifo中少一个transaction ;而 peek任务是fifo把transaction复制一份发出,内部缓存中的transaction不会减少。一般情况下peek完以后, 还得调get。 上述操作都有阻塞和非阻塞之分。portexportimp的类型也有blocking和nonblocking之分。 port/export/imp 类型:put/get/peek/get_peek/transportbloc

11、king/nonblocking/不区分 blocking-nonblocking 之分 imp要多一个参数,除了声明transaction类型(或者 REQRSF类型)以外,还要声明实现这个接口的component I .I/r. connect 的一定是同类型的port/export/imp TLM的关键在于与 imp对应的component中task/function的实现”。 假设 A port.connect(B imp),那么需要实现的 task/function 为: A port B imp Task/fu nctio n Fun cti on uvm block in g p

12、ut port uvm block in g put imp put non block in g put non block in g put imp try putca n put put put put try putca n put block in g tra nsport block in g tra nsport tran sport non block in g tra nsport non block in g tra nsport n b tra nsport tran sport tran sport tran sport nb transport get_peek ge

13、t_peek getpeek try_getca n_gettry_p eekcan peek get/peek/get_peek和put类似,上述task或function必须要实现,如果用不到就写个空函数(章节4.2.9)。 注意上述 task 或者 function 的参数。put 是一个 transaction 参数,get/peek 是 output 的 transaction 参数,transport 是一个 req 参数一个 output 的rsq 参数。 连接用connect函数实现,从名字就可以看出来,这个必须在connect_phase中调。 4.3通信方式 这节应该是本章

14、重点。实际使用中用analysis_port analysis_imp还是port tlm_analysis_fifo port可以根据 实际情况自己决定。 analysis_port(analysis_export)可以连接多个imp (一对多的通信)put和get系列端口与相应imp的通信 通常是一对一的(可以一对多,但是本书没有给出一对多的例子4.2.1章节有介绍)。analysis_port(analysis_export) 更像是一个广播 analysis_port(analysis_export)没有阻塞和非阻塞的概念。它是一个广播,不等与它相连的其他端口的响应。 analysis

15、_port (analysis_export)必须连的 imp 是 analysis_imp.analysis_imp 所在的 component 必须定义个 write 的 function注意:是 function 代码示例:4.3.1示例代码的analysis_port文件夹 componentC 和 B 的代码基本一致。env 的 connect_phase 函数里做 connect: component中有多个imp的时候,如何实现 write函数? 4.3.2 给的例子中,scoreboard 有两个 imp,分另U从 output_agent 禾口 reference-model

16、 的 analysis_port 获取 transaction,然后做 compare.这个时候需要用: uvm_analysis_imp_decl(标记)这个 macro,然后write ”函数变成write_ 标记()”函数,analysis_port 所 在component不用变,还是调 write()函数即可。代码示例如下: 使用macro声明 write函数变名字 analysis_port 所在 component 实现不变。 使用 uvm_analysis_fifo (uvm_tlm_analysis_fifo ) ,analysis_fifo 的本质是一块缓存 + 两个 im

17、p.用 fifo 来实现 port fifo port 使用fifo最重要的是选好两端的port类型,然后根据选好的两端 port类型,来选择fifo上要连接的 imp/exportfifo 本身实现了 write()put()get()peek()等一系列的 function/task,在两端 port 所在的 component 中直接 调就可以。 X y 1 I* I* I ; j | 连接在fifo两端的都是port,所以connect函数的起点是两端。 4.3.3的示例代码: 可以看到env里声明的几个fifo都是connect_phase函数中connect函数括号里的参数。 i_

18、agt.ap、o_agt.ap 禾口 mdl.ap 是 analysis_port mdl.port、scb.exp_port 禾口 scb.act_port 都是 block in g_get_port fifo上有很多export,但是这些export实际都是imp src/tlm1/uvm_tlm_fifo_base.svh 上面连接的 agt_mdl_fifo.analysis_export也是一个 analysis_imp:源代码中实现如下: src/tlm1/uvm tlm fifos.svh uvm_a nalysis_imp#(T,uvm_tlm_a nalysis_fifo#

19、(T)a nalysis_export; fifo 是一个 component,可以调一些函数来debug : used()is_empty()is_full()flush() fifo里缓存深度可以在 new的时候用第三个参数设置。 问题:fifo的两端是不是一般就是analysis_port和blocking_get_port?-感觉4.3.5章节开始一段文字描述是 这个意思。 使用fifo还是imp自己来把握。各有各的好处。 imp可以使用uvm_analysis_imp_decl(_标记)的macro,有时候会很方便。 而analysis_fifo可以用for循环来操作fifo数组,也

20、可以带来代码的简洁。imp不能在connect和new的时候 用for循环。 第5章UVM验证平台的运行 5. Iphase 机制 所有的phase如下图: 中间绿色的是 taskphase,两头青色的是 functionphase component的实例化是在 build_phase中完成,object的实例化可以在任何phase完成。 functionphase中除了 build_phase都是自下而上”的执行-这里的上下是指的树结构中的上下。 build_phase -是“自上而下”- 同层次的兄弟关系的 comp on e nt , buildphase执行顺序是根据 new时候na

21、me的字典序 51.3章节 对于叔侄关系的 component , buildphase执行顺序是深度优先。例如前面UVM树中,“ scb”和“ i_agt.drv ”,因 为i_agt在scb前面,会执行完i_agt,然后drvmonsqr,然后o_agt,然后mon,然后才是scb。 所有compo ne nt的同一个 run timephase是同时开始的。也就是说会等其他 compo nent的上一个 phase结束才 开始当前phase o super.build_phase(phase) 一定要加,其他 phase 的 super.可以不用力口 . phase之间可以跳转。例如在正

22、常工作的时候,发生了的reset,那么应该是 main_phase跳转到reset_phase.例如: 5.1.7章节的示例代码 jump导致main_phase的objection没有被drop.仿真发现这里会有一个 UVMWARINGING报出来,这个问题如 何解决呢?-应该不用管它 simv+UVM_PHASE_TRACET以调试 phase 超时退出机制: 1) 在 test 的 build_phase 里加上 uvm_top.set_timeout(500ns,0); 2) defineUVM_DEFAULT_TIMEOUT500ns 3) simv+UVM_TIMEOUT=”500

23、ns,YES 控制objection的时机: 推荐在sequenee里的body () task中实现控制 objection 5.2.2章节示例代码: 注意用starting_phase的判断。 给 main_phase 设置 drain_time。所谓 drain_time,就是 main_phase 结束之后经过 drain_time 时间以后再进入 post_main_phase。 在 test 的 main_phasetask 中使用 set_drain_time 函数: objection的调试 simv+UVM_OBJECTION_TRACE 5.3章节介绍了 domain ,我

24、觉得基本不会用这个吧 ? 第6章UVM中的sequence sequencer 将 sequenee 传递给 driver.弓I入 sequenee,带来的变化: 1) uvm_transaction 的派生类变成 uvm_sequence_item 的派生类 2) 需要 sequencer 3) drivermain_phase 有变化 4) 启动 sequenee (般在 case 的 build_phase 中) 上述变化反映到代码中,如图6.1.2章节的示例代码 下图中有两种方法实现my_seque ncer sequenee的启动方式(3种): 1 )在case的main_phase

25、中:注意要设置 cseq的staring_phase。我觉得书上6-5代码清单里有两个地方写的不 合理,一个是start的参数应该是sqr的路径,另外是少了设置starting_phase 2) 注意在 case 的 build_phase 中 3) 更推荐用下面这种方式: sequenee 被启动后,会自动执行sequenee 的 bodytask (以及 pre_bodymid_bodypost_body ) 在同一个sequencer上可以启动多个 sequenee,因为启动了多个,所以不能设置default_sequnee 了,需要用上 -来源网络,仅供个人学习参考 面第一种方法来启动

26、 sequenee.但是sequenee的嵌套可以解决这个问题(上层 sequenee做 default_sequence6.4 章节) sequenee 可以用 uvm_do_priuvm_do_pri_with 等 macro 来设置优先级 priority,当一个 sequencer 上有多个 sequenee 的时候,这个优先级就有意义了。 优先级就带来sequencer的仲裁算法。默认的仲裁算法是 SEQ_ARB_FIFO杨哥遵循陷入先出顺序,不考虑优先级), 所以设置优先级以后,需要改变仲裁算法。 在 ease 的 main_phase 中调函数 set_arbitration()

27、 前面提到的嵌套 seque nee”也可以像上面这样来设置仲裁算法。 sequencer 的操作: lock()grab()获取独占权。unlock()ungrab()释放独占权 is_relevant()设置sequenee有效和无效。返回值 1有效,返回值 0无效 wait_for_relevant()当 sequencer 发现启动的所有 sequenee 都无效的时候,会自动调wat_for_relevant()task 。在 wait_for_relevant()task 中,必须使 sequenee无效的条件清除 。 is_relevant()和wait_for_relevant

28、()如果需要的话,一般是成对重载。 I ,-1, 6.3sequence 相关 macro 及实现 最重要的是uvm_do系列宏,尤其是在引入 virtualsequencer以后uvm_do_on系列宏用的会很多。 uvm_do_on_pri_with(SEQ_OR_ITEM,SEQR,PRIORIT,CONSTRAINTS)uvm_d(系列 macro 都是来源于这个最长的 macro 除了 uvm_do 系列 macro 之外,还可以用 uvm_ereate+uvm_send。使用 uvm_ereate+uvm_send 的优势是可以 在两个macro之间加一些赋值操作等,当然也可以把约

29、束随机加在这里。uvm_create是实例化transaetion, uvm_send 是把 transaction 发送出去。 uvm_rand_senduvm_rand_send_priuvm_rand_send_withuvm_rand_send_pri_with与 uvm_do 系列 macro 类彳以 start_item和finish_item上述macro的实际实现函数我觉得我们代码里应该不会用这两个函数。 taskpre_do(bitis_item) fun etio nvoidmid_do(uvm_seque neetemthis_item) fun eti on voidp

30、ost_do(uvm_seque nce_itemthis_item) 注意上述task/function的参数。mid_do和post_do因为参数是基类对象,函数重载里可能需要做$cast. 6.4sequence进阶应用 p.- . I I 前面提至U了 uvm_do 系列宏既可以用在uvm_sequence_item 上也可以用于 uvm_sequenee,所以 sequenee可以嵌 套。 sequenee中可以有rand成员,并且可以把 rand成员和transaction的rand成员约束起来。 通过上面的约束,上层sequenee里可以约束下层 sequenee里transac

31、tion的成员: sequenee的参数代表了它的req和rsp的uvm_sequence_item派生类的类名。如果需要发送不同 uvm_sequeneetem 派生类的对象,那么需要把 sequenee、sequencer禾口 driver参数声明成基类 uvm_sequeneetem 。 由于是基类,所以在 driver中seq_item_port.get_next_item(req) 的时候要做$cast转换.因为sequenee默认参数就 是 uvm_sequence_item,所以不用写。 6.4.3示例代码: driver中的cast操作 实际的testbench中,很可能会在s

32、equencer里加入一些成员变量, 一般这种情况下要 declarep_sequencer这个指 针。用 macro -uvm_declare_p_sequencer(sequencer 类名)在 sequenee 中可以实现: 6.4.4 章节示例 问题:p_sequencer的声明 macro是不是一直加着-直接写在 base_sequenee里比较好。 -来源网络,仅供个人学习参考 可以做一个 base_sequenee,需要 p_sequencer的声明的话,写在 base_sequenee里,这样就不用每个sequenee都 声明 p_sequencer 指针了。 6.5virtu

33、alsequence virtualsequence(virtualsequencer)是特色。如下图所示: 系统级环境里可能有多个env,带来了多个 sequencer/sequenee ,这样在case里不好维护。实现一个 virtualsequencer,里面包括指向各个 sequencer的指针;而 virtualsequenee 就像前面介绍的 sequenee嵌套”一 样实现。 由于virtualsequencer里有实际sequencer的指针,所以肯定不能用typedefuvm_sequncer.”来实现。同时, 由于 virtualsequencer 有成员了,所以在virt

34、ualsequenee 里要 declarep_sequencer,并且指向 virtualsequencer. base_test的connect_phase函数中,要把 virtualsequencer里的成员赋值到各个 env的sqr上。-所以 virtualsequencer禾口各个env是同级的 所谓virtual ” 是说它本身不会发送 transaction,所以 virtualsequencer 禾口 virtualsequenee 者E不用写 transaction 的 参数(用了默认的参数)。 6.5.3章节示例代码 virtualsequenee :声明 p_sequen

35、cer 指针,注意 uvm_do_on 的 sequencer 参数 virtualsequencer 声明指针 base_test 在 connect_phase 中连接 sequencer case:设置 virtualsequencer 的 main_phase 的 default_sequenee 为 virtualsequenee. 前面提到了 objection的控制在 sequenee的bodytask中实现。现在引入了 virtualsequenee以后,objection的控制 就移至U顶层 virtualsequenee 的 bodytask 中。 sequenee中尽量不

36、要用 forkjoin_none,避免执行到 endtask 虽然sequenee不是component,但是也可以在 sequenee中使用uvm_config_db(类似于tp_tb中使用)。 在case中对sequenee的成员用 uvm_config_db#(类型):set()的时候要注意:sequenee由于是一个 object,它的名 字可能不确定,所以这里一般用通配符。而在sequenee中get的时候,则使用 uvm_root:get()/或者null和 get_full_name(),作为前两个参数。 6.6.1示例代码set用通配符和get的路径参数 在sequenee中可

37、以对testbench中的component的成员使用 uvm_config_db#(类型):set(),同样因为路径的问题, 第一个参数一般是 null或者uvm_root:get() 书上还给了一个设置 sequenee自己的成员的例子,不知道有啥用. 6.6.3章节介绍了 uvm_config_db的wait_modifiedtask,参数只有 3个,和get前三个一样。 p. I I 6.7response sequencesequencerdriver 的参数有两个 :req 类型禾口 rsp 类型,默认情况下 rsp禾口 req 一样的类型。当sequenee 需要driver返回

38、response的时候,就需要用到 rsp 了。 sequenee 中在 uvm_domacro 之后调 get_reponse(rsp)task,而在 driver 中增加的代码较多: 6.7.1章节示例代码 get_reponse 禾口 put_response 对应。注意 driver 中必须有 set_id_info 函数。 put_response可以省略:需要 item_done函数带rsp参数:seqtem_port.item_done(rsp) 但是当有多次 rsp的 时候,就不能这么用了。多次的时候只能是调多次get_reponse和put_response get_resp

39、onse是一个阻塞的task,当sequenee没有获取到 driver返回的rsp的时候,会阻塞住sequenee的 body(),所以当driver不能及时返回rsp的时候,get_responseput_response这个机制就有问题了。UVM的解 决方法是使用 response_handler函数: -来源网络,仅供个人学习参考 在pre_body()函数中use_reponse_handler()打开这个功能,然后重载 response_handler(uvm_sequence_itemresponse) 这个函数 一般需要 $cast给 sequenee 中的 rsp 成员.而

40、sequenee 的bodytask里就不用再调 get_response 了 6.7.3章节代码示例: rsp和req的类型可以不同,这个时候注意sequencedriversequencer的参数 6.8sequencelibrary sequencelibrary 是一系歹U sequenee 的结合。uvm_sequence_library 本身是 uvm_sequenee 的派生类。 实现sequence_library的时候要注意: 1) 在 new 函数里要增加 init_sequence_library()函数 2) 增力口 uvm_sequence_library_utils

41、( 类名)的 macro 对于里面的 sequenee 只需要增加一个 macro: uvm_add_to_seq_lib(sequenee 类名,sequence_library 类名) 一个sequenee可以加入至U不同的sequence_library中 使用 sequence_library 可以有效简化 Testcase,因为 case 中设置 sqr 的 main_phased 的 default_sequenee 是 sequence_library 类名::type_id:get() 可以使用sequence_library_cfg来控制sequence_library里迭代次数、选择算法以及sequenee的个数。但是我觉得 使用简化的方法更方便和直观(不用sequence_library_cfg类,而是直接对 sequence_library对象的成员赋值): 6.8.4示例代码: 在case的build_phase里实现,需要把 sequence_librarynew出来 l 第8章UVM中的factory 机制 重点章节uvm特色 UVM的factory机制也是建立

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论