? 由于此宏创建了新的类定义,最好将此宏放到一个共享的作用域,比如systemverilog包.
当组件确实需要对同一接口进行多种实现的时候,使用这些新类(类似标准的记分牌组件)
使用通用的有意义的后缀。例如,后缀_inport1和_outport1就比较合理,因为它们提供了一些连接实现相关的信息
后缀以下划线'_'开头,让实现函数名能够通过下划线分隔(比如write_inport1)
?
?
?
实例4-13: `uvm_*_imp_decl宏
以下是使用宏的记分牌(scoreboard)的简单示例.
1. 2. 3. 4. 5. 6. 7. 8. 9.
package my_analysis_imps_pkg; import uvm_pkg::*;
`include \
`uvm_analysis_imp_decl(_inport1) `uvm_analysis_imp_decl(_inport2) `uvm_analysis_imp_decl(_outport2) `uvm_analysis_imp_decl(_outport2) endpackage: my_analysis_imps_pkg package scoreboard_pkg:
10. import uvm_pkg::*;
11. `include \12. import my_analysis_imps_pkg::*; 13. import mytx_pkg::*; 14. mytx q1[$], q2[$];
15. class myscoreboard extends uvm_component;
16. uvm_analysis_imp_inport1#(my_tx, myscoreboard)
in_export_1;
17. uvm_analysis_imp_inport2#(my_tx, myscoreboard)
in_export_2;
18. uvm_analysis_imp_outport1#(my_tx, myscoreboard)
out_export_1;
19. uvm_analysis_imp_outport2#(my_tx, myscoreboard)
out_export_2;
20. function new(string name, uvm_component parent); 21. super.new(name,parent);
22. in_export_1 = new(\
23. in_export_2 = new(\24. out_export_1 = new(\25. out_export_2 = new(\26. endfunction
27. function void write_inport1(mytx t); 28. q1.push_back(t); 29. endfunction
30. function void write_inport2(mytx t); 31. q2.push_back(t); 32. endfunction
33. function void write_outport1(mytx t); 34. mytx t1, t2;
35. t1 = q1.pop_front();
36. t2 = t.transform1(); //execute some transformation
function
37. if(!t1.compare(t.transform1())) 38. `uvm_error(\
$psprintf(\t2.sprint()))
39. endfunction: write_outport1
40. function void write_outport2(mytx t); 41. mytx t1, t2;
42. t1 = q2.pop_front();
43. t2 = t.transform2(); //execute some other
transformation function
44. if(!t1.compare(t.transform1())) 45. `uvm_error(\
$psprintf(\t2.sprint())) 46. endfunction 47. endclass
48. endpackage: scoreboard_pkg;
(译者补充:将来可以根据需要将任意一个port连接到相应的analysis port上去,从而完成不同的监控动作)
下次内容:UVM工厂
UVM实战指南——第4部分
2010-12-31 23:57:20| 分类: SystemVerilog|字号 订阅
译者前序:
2011年马上就到了,2010年最后一篇。预祝2011年快乐常在。
英文来源:http://www.low-powerdesign.com/article_Cadence-UVM_101810.html
?
UVC: 其翻译借鉴OVM中OVC(Open Verification Component)的定义,UVC应该是Universal Verification Component:通用验证组件。两者本质相同。
Factory属于软件设计中设计模式中的一种,在面向对象软件开发中常常会用到,可以参考设计模式相关书籍做进一步理解。
override翻译为重载,或者覆盖。在软件领域中一般译作重载。是指对象被同一祖宗的另外一个对象所覆盖。利用了面向对象中运行时动态数据类型识别(RTTI)机制来实现。
?
?
? handle翻译为句柄,可以将之理解为指针,一个系统维护的间接指针,系统可以通过这个句柄来找到对象的内存地址。
object一般翻译成对象,但是此书中有时候会表示uvm_object,以示和
uvm_component区分。component翻译为组件,一般也会暗示是指uvm_component. sequence_item翻译为交易序列项,其实它是用来替换transaction的,也可以将之理解为事务和交易。UVM中不建议使用uvm_transaction,而建议使用
uvm_sequence_item来对交易和事务进行建模。我将之翻译为交易序列项的有点拗口,只是为了表示它可以理解为一般的交易。
callback翻译为回调,也就是软件编程中回调函数的概念。可以理解为内建一个数组,数组的元素就是函数指针,注册回调函数也就是增加数组元素。在调用的时候,对数组里面每一个元素,都调用其指向的函数。前提是这些函数的原型是一模一样的,也就是返回值和参数是一模一样的。
?
?
?
? ?
typedef来自于C语言,用于类型简化声明,这里翻译成类型别名。
reference在C++中被翻译为引用,其实本质上也是指针的实现,所以这里为了说明清楚,有时候也直接使用指针来翻译reference.
译者后序:
? 目前网站上只提供了这本书的第四章内容,看完之后感觉很不错,讲解很清楚,译者并不是专业的IC验证人员也能够大体掌握。可惜其他章节的内容译者没有办法获得,期待这本书能够出影印版本,以帮助我们提升IC验证的能力。
4.7 UVM工厂 作为验证计划和任务的一部分,用户可能需要扩展其通用的验证环境的原始行为。和设计不一样,对于设计,能够完全确定所有想要的功能和要求。而验证过程是不固定的,动态的,难以预测的。一个可复用的验证环境,开发人员不能够预料项目以及未来项目的每一个测试边界(corner)条件。UVM工厂的目标是实现一个高级的经典的软件工厂设计模式用来创建通用代码,可以在运行时动态决定需要分配内存的对象的子类型。请看下面的可复用类型定义: 实例4-14: 使用UVM非工厂模式分配对象内存 第一个例子使用new()函数来分配内存。此例子之后,我们会解释为什么不建议使用new()方式,以及它在复用上的局限性。 1. 2. 3. 4. 5. 6. 7. 8. 9.
class driver extends uvm_component `uvm_component_utils(driver)
function new(string name, uvm_component parent); super.new(name, parent); endfunction
virtual task drive_transfer(); ... endtask endclass: driver
10. class agent extends uvm_component; // bad example that uses new() 11. `uvm_component_utils(agent) 12. driver my_driver;
13. function new(string name, uvm_component parent); 14. super.new(name, parent); 15. // create the driver
16. my_driver = new (“my_driver”,this); // using new() 17. endfunction 18. endclass: agent
为了方便讨论,假设用户希望将此agent作为验证组件集成到测试向量中去,并且希望定制driver_transfer()任务的实现,让其能够打印一些信息。OOP(面向对象程序设计)建议用户继承产生一个新的组件,如下: 1. 2. 3. 4. 5. 6. 7. 8. 9.
class my_project_driver extends driver; `uvm_component_utils(my_project_driver) virtual task drive_transfer(); super.drive_transfer();
`uvm_info(\ endtask
function new(string name, uvm_component parent); ....
endfunction
10. endclass: my_project_driver
这个扩展得来的新类并不足够满足要求,因为agent例化的是之前定义的driver组件而不是新扩展的my_project_driver组件。为了解决这个问题,整合人员不得不扩展agent类以及一些其他一些例化了driver的类。由于driver的父组件定义需要被扩展,则此通用验证组件(UVC)的接口定义也需要扩展,因此,产生了一系列连锁反应,需要对整个验证环境的许多代码进行修改。UVM工厂模式的引入,允许在agent之外对driver进行重载,巧妙而漂亮的解决了这个问题。通过调用create()函数而不是new()函数,来创建dirver对象。此create()函数使用一个中心服务设施(译者注:可以将此设施理解为工厂)来分配对象内存及返回句柄。一个使用工厂的更加复用的agent版本如下所示: 实例4-15: 使用UVM工厂 1. 2. 3. 4. 5. 6. 7. 8. 9.
class agent extends uvm_component; `uvm_component_utils(agent) driver my_driver;
function new(string name, uvm_component parent); super.new(name, parent); // create the driver
my_driver = driver::type_id::create(\ endfunction endclass: agent
当写完此代码之后,用户可以使用如下的方法在系统中重载所有的此driver类型对象: set_type_override_by_type(driver::get_type(), my_project_driver::get_type());