Chpater 22 UVM Agent
- 将测试平台不断模块化是一件美妙的事情,无论我们使用它来封装硬件中的块,固件中的子程序还是软件中的对象,模块化都会隐藏复杂性并改善生活。 模块化还允许我们将经过测试的功能重用为硬件中的IP,固件中的库和软件中的类库。
- 成功模块化的关键是支持严格且不变的接口。定义接口允许用户(以及未来的自我)自信地使用模块化组件,而不必担心其内部工作。
- UVM 提供了Agent, configuration objects,configuration database实现UVM的模块化。Agent允许我们封装相似的对象,cfg object允许我们存储agent需要的信息,cfg databas允许我们传递配置信息到同类型的不同Agent。
22.1 模块化前后的测试平台
- 模块化前的测试平台如下所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/2019033023282598.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5NTU2MTQz,size_16,color_FFFFFF,t_70)
测试品台需要产生激励,检查结果,监测覆盖率。但是这些功能都是分开的一个个碎片,如果我们的设计中使用大量的TinyALU,我们需要拷贝所有的对象,port来实现重用。
- 模块化后的测试平台如下所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190330232835398.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5NTU2MTQz,size_16,color_FFFFFF,t_70)
我们使用和此前一致的objects,并使用uvm_component类型的组件uvm_agent来封装这些组件。各组件间的连接方式不变。
此外,我们在uvm_agent顶层声明了两个analysis port,这样我们可以在更高的层次中看到uvm_agent中传输的数据,但是scoreboard和coverage不做任何改变。
虚线中的模块包括tester, command_f, driver对象,只有在初始化时希望产生激励是才激活,否则uvm_agent中不包括这三个模块,但我们仍可以使用agent的其他组件监控TinyALU。
22.2 创建TinyALU Agent
- TinyALU看来和env十分类似,他们之间的区别是uvm agent引入configuration机制来传输BFM,并且可以决定agent中是否包含stimulus。
- TynyALU Agent中包含了此前测试平台中所有的组件和FIFO,并且定义了agent定测接口的两个analysis port。
class tinyalu_agent extends uvm_agent;
`uvm_component_utils(tinyalu_agent)
tinyalu_agent_config tinyalu_agent_config_h;
tester tester_h;
driver driver_h;
scoreboard scoreboard_h;
coverage coverage_h;
command_monitor command_monitor_h;
result_monitor result_monitor_h;
uvm_tlm_fifo #(command_transaction) command_f;
uvm_analysis_port #(command_transaction) cmd_mon_ap;
uvm_analysis_port #(result_transaction) result_ap;
function new (string name, uvm_component parent);
super.new(name,parent);
endfunction : new
function void build_phase(uvm_phase phase);
if(!uvm_config_db #(tinyalu_agent_config)::get(this, "","config",tinyalu_agent_config_h))
`uvm_fatal("AGENT", "Failed to get config object");
is_active = tinyalu_agent_config_h.get_is_active();
if (get_is_active() == UVM_ACTIVE) begin : make_stimulus
command_f = new("command_f", this);
tester_h = tester::type_id::create( "tester_h",this);
driver_h = driver::type_id::create("driver_h",this