Chapte 16 – Using Analysis ports in a testbench
测试平台中所有的组件可以分为两种:驱动DUT运行 & 观察DUT变化。
我们此前的测试平台中,tester_h就是用于驱动仿真平台运行,scoreboard_h和coverage_h用于监控DUT的行为。从UVM的角度来看,scoreboard和coverage组成了测试平台的_analysis layer_.所以,用于传输数据的端口被称作uvm_analysis_port.
16.1 重复代码
如果两段代码在实现一致的功能,就像是露营时打开帐篷:You are inviting bugs in。
此前,我们的测试平台就具有这样的代码,在covereage和scoreboard中都需要从BFM收集cmd信号,但是这样的工作其实做一次就足够了。
我们希望可以在BFM的pins上,检测cmd的变化,并将数据送至coverage和scoreboard。因为scoreboard需要计算结果,所以需要在上收集result,并送至scoreboard。
16.2 将analysis port用于测试平台
测试平台的整体框架图如下:
在此前的测试平台,tester_h中包含BFM的句柄,现在BFM有了两个新的句柄,command_monitor和result_monitor. BFM识别出TinyALU的command和results并将其送至monitor,在monitor中调用analysis的write函数,将数据送至coverage_h和scoreboard_h中。
16.2.1 bfm模块的处理
OOP编程最大的优势就是,我们可以通过共享对象句柄为测试平台的各个模块增加功能。现在我们使用tinyalu_bfm将测试平台的其余部分连接起来。
- 以下是tinyalu_bfm模块的部分代码:
interface tinyalu_bfm;
import tinyalu_pkg::*;
command_monitor command_monitor_h; //声明两个Monitor的句柄
result_monitor result_monitor_h;
assign op = op_set;
always @(posedge clk) begin : cmd_monitor
bit new_command;
if (!start)
new_command = 1;
else
if (new_command) begin //监控ALU的commands
command_monitor_h.write_to_monitor(A, B, op); //每当有新的command到来,调用cmd_monitor的write_to_monitor函数将数据送至command_monitor
new_command = (op == 3'b000); // handle no_op
end
end : cmd_monitor
always @(negedge reset_n) begin : rst_monitor //监控ALU的commands
command_monitor_h.write_to_monitor(A, B, rst_op); //当reset_n的信号有效时,调用cmd_monitor的write_to_monitor函数,将reset_op送至command_monitor
end : rst_monitor
//监控ALU的results
always @(posedge clk) begin : rslt_monitor //当操作结束,done信号有效时,调用result_monitor的write_to_monitor函数,将result数据送至result_monitor
if (done)
result_monitor_h.write_to_monitor(result);
end : rslt_monitor
endinterface : tinyalu_bfm
16.2.2 command_monitor模块的处理 (monitor)
在command_monitor的build_phase中,声明virtual interface bfm,在仿真开始时,通过uvm_cfgdb机制get bfm,然后将自己的句柄传输给bfm中的command_monitor_h。
(result_monitor以同样的方式实现此功能,这里就不再贴代码了)
- command_s数据结构如下图:
- 以下是command_monitor模块的代码:(analysis port就在monitor中)
class command_monitor extends uvm_component;
`