uvm实战学习笔记.doc_第1页
uvm实战学习笔记.doc_第2页
uvm实战学习笔记.doc_第3页
uvm实战学习笔记.doc_第4页
uvm实战学习笔记.doc_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

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

文档简介

1、UVM实战(卷1)学习笔记看了第 1/2/3/4/5/6/8/9.1这几个章节。第一章是综述,第二章是一个具体的例子,学习笔记从第三章相关内容开始。我个人觉得UVM 重要的部分(特点的部分):1) factory 机制( override config_db )2) TLM 传递3) phase 机制4) sequence-sequencer 以及 virtual seq/sqr内容中的截图基本来自于 UVM 源代码、书自带的例子和 uvm1.1 应用指南及源代码分析这个 PDF里的。 需要结合书( UVM 实战(卷 1)第 1 版)来看这个笔记。第3章 UVM基础3.1 uvm_compon

2、ent和 uvm_object常用的类名字:这个图是从作者张强的uvm1.1 应用指南及源代码分析里截得,不如书上uvm_sequencer 也是代码里必须有的,所以我加了uvm_sequencer3.1.1 里的图好。uvm_void 是一个空的虚类。在src/base/uvm_misc.svh 中定义:红框的是我们搭testbench 的时候用的比较多的基类。常用的 uvm_object 派生类:sequencer 给 driver 的 transaction 要 派 生 自 uvm_sequence_item , 不 要 派 生 自 uvm_transaction所有的 sequence

3、 要派生自 uvm_sequence 或者 uvm_sequence 的派生类,可以理解为 sequence 是 sequence_item 的组合(集合) 。 driver 向 sequencer 索要 item ,sequencer 检查是否有 sequence 要发送 item ,当发现有 item 待发送时,就把这个 item 发给 driver.常用的 uvm_component派生类:所有的 driver 要派生自uvm_driver.driver 用来把 sequence_item 中的信息驱动到DUT 端口上,从transaction-level 向 signal-level

4、的转换。uvm_driver 需要参数( REQ RSP),比uvm_component增 加 了 几 个 成 员 。 重 要 的 是seq_item_port和req/rsp.( src/comps/uvm_driver.svh )monitor/scoreboard派生自uvm_monitor和 uvm_scoreboard , 但是uvm_monitor和uvm_scoreboard 并没有在uvm_component基础上做扩展。src/comps/uvm_monitor.svhsequencer 要派生自 uvm_sequencer. sequencer 做了很多扩展, 但是如果我们

5、自己写的 sequencer 里没有增加成员的话,可以直接写如下代码:typedef uvm_sequencer #( 传递的 sequence_item 类名 )sequencer 类名 ;因为sequencer在agent中例化,所以一般写在agent类文件里。reference_model派生自uvm_component.agent 要派生自uvm_agent. uvm_agent 里多了一个is_active 的成员。一般根据这个active来决定是否实例化driver 和 sequencer.is_active 变量的数值需要在env 的 build_phase置完成(可以直接设置,

6、也可以用uvm_config_db#(int):set )。里设env 要派生自 uvm_env. uvm_env 没有对 uvm_component 扩展。src/comps/uvm_env.svh所有的 test 都要派生自 uvm_test 或者它的派生类。 uvm_test 也没扩展 src/comps/uvm_test.svhuvm_object 和 uvm_component的 macromacro非常重要,事关把这些类的对象注册到factory机制中去。uvm_object macro1)对于 uvm_sequence_item 就统一用 (假设不用 parameter) :uv

7、m_object_utils_begin(item类名 ). field_automation uvm_object_utils_end2)对于 uvm_sequence ,要加上uvm_object_utils(sequence类名 )可能还需要 uvm_declare_p_sequencer(sequencer 类名 )的声明uvm_component macro对于 driver monitor reference_model scoreboard sequencer case agent env这些uvm_component 派生类都要加上:uvm_component_utils( 类

8、名 )uvm_component 里的成员也可以像uvm_object 里成员一样,用field_automation机制。field_automation机制:对于 uvm_object 派生类来说, field_automation机制让对象自动有的copy compare print packunpack 等函数,简化了实现uvm_component 派生类里一些function/task的工作量对于 uvm_component 派生类来说, field_automation机制最重要的是可以在 build_phase 中自动获取uvm_config_db#():set() 的数值( 必

9、须加 super.build_phase(phase) )- 也就是不用写 uvm_config_db#():get()注意:field_automation的 macro 的类型要和uvm_config_db 的参数类型一致:如下示例代码,field_int vs uvm_config_db#(bit47:0)这个时候 super.build_phase() 是不起作用的。想要起作用的话,需要用clone = new + copy 源代码中可以看到 clone 函数一上来会做一次 create,然后调 copy 函数 src/base/uvm_object.svh3.2 UVM 的树形结构u

10、vm_component 的 new/create 要注意第一个参数是名字,第二个参数是UVM 真正的树根是“uvm_top ” . 根据上面这个树结构,可以看出一个个parent 指针。component的 parent 是什么。 uvm_top 的 parent 是 null 。当一个 component 在实例化的时候,如果parent 参数设成null ,那么 parent 参数会被仿真器自动设置成uvm_root 的实例 uvm_top.在 6.6.1 章节里也提到了, sequence 在 uvm_config_db# ():get()的时候,第一个参数设成“ null ”,实际就

11、是uvm_root:get()3.5.1 章节也提到了这个层次结构函数:get_parent()get_child(string name)这两个分别获取parent 指针和指定名字的child 指针。get_children(ref uvm_component children$) 获取所有的 child 指针 get_num_children() 获取 child 个数get_first_child(ref string name) get_next_child(ref string name) 获取 child 的名字(反映到 string name 上),返回值是 0/1 两种情况应用

12、参考代码如下(改动的2.5.2 例子中的 my_agent.sv ):注意:上述代码是在connet_phase 中实现的。上述代码的打印结果如下:my_agents name is uvm_test_top.env.i_agt, parents full path is uvm_test_top.env, children numis3uvm_test_top.env.i_agt0 child: drv - full path:uvm_test_top.env.i_agt.drvuvm_test_top.env.i_agt1 child: mon - full path:uvm_test_t

13、op.env.i_agt.monuvm_test_top.env.i_agt2 child: sqr - full path:uvm_test_top.env.i_agt.sqrThis should be i_agt. my_agents name is uvm_test_top.env.i_agt uvm_test_top.env.i_agt first child name is drv uvm_test_top.env.i_agt next child name is mon uvm_test_top.env.i_agt next child name is sqrmy_agents

14、name is uvm_test_top.env.o_agt, parents full path is uvm_test_top.env, childrennum is1uvm_test_top.env.o_agt0 child: mon - full path:uvm_test_top.env.o_agt.monUVM_WARNING /tools/synopsys/vcs/G-2012.09/etc/uvm/src/base/uvm_component.svh(1846) 0: uvm_test_top.env.o_agt NOCHILD Component with name drv

15、is not a child of component uvm_test_top.env.o_agtThis should be o_agt. my_agents name is uvm_test_top.env.o_agt uvm_test_top.env.o_agt first child name is mon3.3 field automation机制注意数组类型的field macro比一般的要少real和event的macro.一般的对于enum类型有3 个参数,而数组的只有2 个参数。联合数组的macro比较多常用函数需要注意bit 个数。pack unpack pack_byt

16、es unpack_bytes pack_ints unpack_ints返回值都是field-automation标记位17bit 中 bit0copy bit1no_copy bit2compare bit3no_compare bit4printbit5no_print bit6record bit7no_record bit8pack bit9no_packUVM_ALL_ON 是 b000000101010101UVM_ALL_ON|UVM_NO_PACK 这样就会忽略掉pack bitfield-automation的 macro 可以和 if 结合起来,参考3.3.4 的代码uv

17、m_object_utils_begin(my_transaction)uvm_field_int(dmac, UVM_ALL_ON)uvm_field_int(smac, UVM_ALL_ON)if(is_vlan)beginuvm_field_int(vlan_info1, UVM_ALL_ON)uvm_field_int(vlan_info2, UVM_ALL_ON)uvm_field_int(vlan_info3, UVM_ALL_ON)uvm_field_int(vlan_info4, UVM_ALL_ON)enduvm_field_int(ether_type, UVM_ALL_O

18、N)uvm_field_array_int(pload, UVM_ALL_ON)uvm_field_int(crc, UVM_ALL_ON | UVM_NOPACK)uvm_field_int( is_vlan, UVM_ALL_ON | UVM_NOPACK)uvm_object_utils_end这个 is_vlan 变量可以在sequence 里约束成0 或 1,来实现vlan 或非 vlanps: 我觉得这个地方代码其实写成像 3.3.3 里的有一个 crc_error 的 rand bit 的更合理一些。然后 crc_error 是 UVM_ALL_ON|UVM_NOPACK,而 c

19、rc 是 UVM_ALL_ON3.4 UVM 打印信息控制get_report_verbosity_level()set_report_verbosity_level(UVM_HIGH)只对当前调用的component 起作用set_report_verbosity_level_hier(UVM_HIGH)对当前及下面所有的component 起作用simv +UVM_VERBOSITY=UVM_HIGH命令行方式-我觉得用这个就可以了重载打印信息:set_report_severity_override(UVM_WARNING,UVM_ERROR); 上述函数都是在 connect_phas

20、e 及后面的 phase 使用设置UVM_ERROR到达一定数量结束仿真set_report_max_quit_count(int)get_report_max_quit_count()设成 0 就是无论多少error返回如果是0,说明无论多少都不退出error 都不退出设置在main_phase前调用。simv +UVM_MAX_QUIT_COUNT=103.4.43.4.53.4.63.4.7 我觉得应该用不大到,就不做笔记了3.5 config_db 机制uvm_config_db#( 类型 ):set/get(component指针 ,”,变量名字 ”,para4)都是 4 个参数:第

21、一个参数是一个component 指针,如果是 null 的话,相当于 uvm_root:get()第二个参数是个路径字符串,第一和第二两个参数组和成一个完整的路径第三个参数对于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

22、的时候,看 set 的第一个参数,层级越高,优先级越高。调用 set 的时候,第一个参数尽量使用this同层次设置的时候是时间优先非直线设置的时候注意第一和第二参数的使用, 如果需要 parent 指针,则要用 this.m_parentconfig_db 机制支持通配符,但是作者不推荐使用通配符。 但是在对 sequence 的成员 set的时候需要用通配符(6.6.1章节)。使用如下函数调试config_dbcheck_config_usage() print_config(1/0)这两个函数在 connect_phase 函数中调simv +UVM_CONFIG_DB_TRACE注意:第

23、二个参数设置错误不会报错! - config_db 机制务必要注意参数的书写。第 4 章 UVM 中的 TLM1.0 通信TLM 是 Transaction Level Modeling 缩写这章要搞清楚port export imp fifo 以及几种操作function/task和对应 component 中要实现的 function/task下面的箭头方向都是控制流的方向,不是数据流方向。我觉得作为一个VMM 用户会觉得TLM 有点难理解,总想用VMM_CHANNEL 去套,结果把自己搞晕。像port 等其实是调imp 所在 component 的 task/function.我看 UV

24、M 源代码里有一个uvm_seq_item_pull_port的 class,它的基类是uvm_port_base.在uvm_driver 的成员 seq_item_port 就是这个类型的。与它对应的是uvm_seq_item_pull_imp ,uvm_sequencer 的成员 seq_item_export 就是这种类型。在my_agent.sv 中会 connect 它们。4.2 端口互连port可以是动作的发起者,exportportexportimpport是动作接收者,但是需要以一个impportimp 也可以 portimp export来结束。impportimp用的较多,

25、portportimp可以用port指针赋值来实现portport(4.3.2章节 )操作:put get/peek transport, transport相当于一次put+ 一次 getpeek 和 get 的不同( 4.3.4 章节) : 使用 uvm_tlm_analysis_fifo的时候,get任务会使fifo中少一个 transaction ;而 peek 任务是 fifo 把 transaction 复制一份发出, 内部缓存中的 transaction 不会减少。 - 一般情况下 peek 完以后,还得调 get。上述操作都有阻塞和非阻塞之分。port export imp的类

26、型也有blocking 和 nonblocking之分。port/export/imp类 型 :blocking-nonblocking 之分put/get/peek/get_peek/transportblocking/nonblocking/不 区 分imp要多一个参数,除了声明transaction类型(或者REQ RSP类型)以外,还要声明实现这个接口的componentconnect 的一定是同类型的port/export/impTLM 的关键在于“与imp对应的component中task/function的实现”。假设 A_port.connect(B_imp), 那么需要实现的

27、task/function为:A_portB_impTask/functionFunctionuvm_blocking_put_portuvm_blocking_put_imp putnonblocking_putnonblocking_put_imptry_put can_putputputputtry_put can_putblocking_transportblocking_transporttransportnonblocking_transportnonblocking_transportnb_transporttransporttransporttransportnb_transp

28、ortget_peekget_peekget peektry_getcan_gettry_peek can_peekget/peek/get_peek 和 put 类似, 上述 task 或 function 必须要实现,如果用不到就写个空函数(章节 4.2.9 )。注意 上述 task 或者 function 的参数。 put 是一个 transaction参数, get/peek是 output的transaction 参数, transport 是一个 req 参数一个 output 的 rsq 参数。连接用 connect 函数实现,从名字就可以看出来,这个必须在connect_pha

29、se 中调。4.3 通信方式这 节 应 该 是 本 章 重 点 。 实 际 使 用 中 用 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_expor

30、t) 没有阻塞和非阻塞的概念。它是一个广播,不等与它相连的其他端口的响应。analysis_port ( analysis_export )必须连的imp是 analysis_imp.analysis_imp 所在的component 必须定义个write 的 function -注意:是function代码示例: 4.3.1 示例代码的analysis_port 文件夹component C 和 B 的代码基本一致。env 的 connect_phase 函数里做connect :component 中有多个imp 的时候,如何实现write 函数?4.3.2 给的例子中,scoreboar

31、d 有两个imp, 分别从output_agent和analysis_port 获取 transaction ,然后做 compare. 这个时候需要用:uvm_analysis_imp_decl(_ 标记 ) 这个 macro ,然后“ write ”函数变成函数, analysis_port 所在 component 不用变,还是调write() 函数即可。使用 macro 声明reference-model的“write_ 标记()”代码示例如下:write 函数变名字analysis_port 所在 component 实现不变。使用 uvm_analysis_fifo(uvm_tlm

32、_analysis_fifo ), analysis_fifo 的本质是一块缓存+两个 imp.用fifo来实现portfifoport使用 fifo 最重要的是选好两端的port 类型 ,然后根据选好的两端port 类型,来选择 fifo上要连接的imp/exportfifo 本身实现了write() put() get() peek()等一系列的function/task ,在两端 port 所在的 component 中直接调就可以。连接在 fifo 两端的都是port ,所以 connect 函数的起点是两端。4.3.3 的示例代码:可以看到 env 里声明的几个fifo 都是 con

33、nect_phase 函数中 connect 函数括号里的参数。i_agt.ap、 o_agt.ap 和 mdl.ap 是 analysis_portmdl.port 、 scb.exp_port 和 scb.act_port 都是 blocking_get_portfifo 上有很多export ,但是这些export 实际都是impsrc/tlm1/uvm_tlm_fifo_base.svh上面连接的agt_mdl_fifo.analysis_export也是一个analysis_imp: 源代码中实现如下:src/tlm1/uvm_tlm_fifos.svhuvm_analysis_im

34、p #(T, uvm_tlm_analysis_fifo #(T) analysis_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,有时候会很方

35、便。而 analysis_fifo 可以用 for 循环来操作fifo 数组,也可以带来代码的简洁。imp不能在connect和new的时候用for循环。第 5 章 UVM 验证平台的运行5.1 phase 机制所有的 phase 如下图:中间绿色的是task phase,两头青色的是function phasecomponent 的实例化是在build_phase 中完成, object 的实例化可以在任何phase 完成。function phase 中除了 build_phase 都是“自下而上” 的执行- 这里的上下是指的树结构中的上下。 - build_phase 是“自上而下”同层

36、次的兄弟关系的component , build phase 执行顺序是根据new时候name的字典序5.1.3 章节对于叔侄关系的component ,build phase执行顺序是深度优先。例如前面UVM 树中,“ scb”和“ i_agt.drv ”,因为 i_agt 在 scb 前面,会执行完i_agt,然后 drvmonsqr ,然后 o_agt,然后mon ,然后才是scb。所有 component 的同一个 run time phase的上一个phase 结束才开始当前phase。是同时开始的。- 也就是说会等其他componentsuper.build_phase(phase

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

38、FAULT_TIMEOUT 500ns3) simv +UVM_TIMEOUT=”500ns,YES”控制 objection 的时机:推荐在 sequence 里的 body () task 中实现控制 objection 5.2.2 章节示例代码:注意用starting_phase 的判断。给 main_phase 设置 drain_time 。所谓 drain_time ,就是 main_phase 结束之后经过 drain_time 时间以后再进入 post_main_phase 。在 test 的 main_phase task 中使用 set_drain_time 函数:objec

39、tion 的调试simv +UVM_OBJECTION_TRACE5.3 章节介绍了domain ,我觉得基本不会用这个吧?第 6 章 UVM 中的 sequencesequencer 将 sequence 传递给 driver. 引入 sequence,带来的变化:1) uvm_transaction 的派生类变成uvm_sequence_item 的派生类2) 需要 sequencer3) driver main_phase 有变化4) 启动 sequence(一般在case 的 build_phase 中)上述变化反映到代码中,如图6.1.2 章节的示例代码下图中有两种方法实现my_se

40、quencersequence 的启动方式 (3 种 ):1)在 case 的 main_phase 中:注意要设置cseq 的 staring_phase 。 我觉得书上6-5 代码清单里有两个地方写的不合理,一个是start的参数应该是sqr 的路径,另外是少了设置starting_phase2)注意在case的 build_phase 中3)更推荐用下面这种方式:sequence 被启动后,会自动执行sequence 的 body task(以及pre_body mid_body post_body )在 同 一 个sequencer上 可 以 启 动 多 个sequence , 因 为

41、 启 动 了 多 个 , 所 以 不 能 设 置default_sequnce 了,需要用上面第一种方法来启动sequence. - 但是 sequence 的嵌套可以解决这个问题(上层sequence 做 default_sequence 6.4 章节)sequence 可以用 uvm_do_pri uvm_do_pri_with 等 macro 来设置优先级 priority, 当一个 sequencer 上有多个 sequence 的时候,这个优先级就有意义了。优先级就带来sequencer 的仲裁算法。默认的仲裁算法是SEQ_ARB_FIFO(杨哥遵循陷入先出顺序,不考虑优先级),所以

42、设置优先级以后,需要改变仲裁算法。在 case 的 main_phase 中调函数set_arbitration()前面提到的“嵌套sequence”也可以像上面这样来设置仲裁算法。sequencer 的操作:lock()grab()获取独占权。unlock() ungrab()释放独占权is_relevant()设置 sequence 有效和无效。返回值1 有效,返回值wait_for_relevant()当sequencer 发现启动的所有sequencewat_for_relevant() task 。 在 wait_for_relevant() task中,必须使0 无效都无效的时候,会自动调sequence 无效的条

温馨提示

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

评论

0/150

提交评论