uvm白皮书练习_ch2_ch222只有factory机制
factory机制的实现被集成在了一个宏中:uvm_component_utils。
这个宏所做的事情非常多,其中之一就是将my_driver登记在UVM内部的一张表中,这张表是factory功能实现的基础。
自动创建一个类的实例并调用其中的函数(function)和任务(task)。
factory机制的实现被集成在了一个宏中:uvm_component_utils。
这个宏所做的事情非常多,其中之一就是将my_driver登记在UVM内部的一张表中,这张表是factory功能实现的基础。
只要在定义一个新的类时使用这个宏,就相当于把这个类注册到了这张表中。
一个run_test语句会创建一个my_driver的实例,并且会自动调用my_driver的main_ phase。仔细观察run_test语句,会发现传递给它的是一个字符串。UVM根据这个字符串创建了其所代表类的一个实例。
根据类名创建一个类的实例,这是uvm_component_utils宏所带来的效果,同时也是factory机制给读者的最初印象。只有在类定义时声明了这个宏,才能使用这个功能。
所以从某种程度上来说,这个宏起到了注册的作用。只有经过注册的类,才能使用这个功能,否则根本不能使用。
请记住一点:所有派生自uvm_component及其派生类的类都应该使用uvm_component_utils宏注册。
除了根据一个字符串创建类的实例外,上述代码中另外一个神奇的地方是main_phase被自动调用了。
在UVM验证平台中,只要一个类使用uvm_component_utils注册且此类被实例化了,那么这个类的main_phase就会自动被调用。
这也就是为什么上一节中会强调实现一个driver等于实现其main_phase。所以,在driver中,最重要的就是实现main_phase。
上面的例子中,只输出到“main_phase is called”。
令人沮丧的是,根本没有输出“data is drived”,而按照预期,它应该输出256次。关于这个问题,牵涉UVM的objection机制。
dut.sv
module dut (
clk,
rst_n,
rxd,
rx_dv,
txd,
tx_en
);
input clk ;
input rst_n ;
input rxd ;
input rx_dv ;
output txd ;
output tx_en ;
reg [7:0] txd;
reg tx_en;
always @(posedge clk) begin
if(!rst_n)begin
txd <= 8'h00;
tx_en <= 1'b0;
end
else begin
txd <= rxd;
tx_en <= rx_dv;
end
end
endmodule
mydriver.sv
`ifndef MY_DRIVER_SV
`define MY_DRIVER_SV
class my_driver extends uvm_driver;
`uvm_component_utils(my_driver)
function new(string name="my_driver",uvm_component parent =null);
super.new(name,parent);
endfunction //new()
extern virtual task main_phase(uvm_phase phase);//调用附近的代码
endclass //my_driver extends uvm_driver
task my_driver::main_phase(uvm_phase phase);
top_tb.rxd <= 8'b0;//初始值复位
top_tb.rx_dv <= 1'b0;
while (!top_tb.rst_n)
@(posedge top_tb.clk);//等个时钟
for(int i =0;i<25;i++)begin
@(posedge top_tb.clk);//等个时钟
top_tb.rxd <= i[7:0];
// top_tb.rxd <= $urand_range(0.255);
top_tb.rx_dv <= 1'b1;
`uvm_info("my_driver","data is driver",UVM_LOW);
end
@(posedge top_tb.clk);
top_tb.rx_dv <= 1'b0;
endtask //my_driver::main_phase
`endif
/*
2023-9-19 07:43:57
ch221
只有driver的验证平台
2023-9-19 07:44:44
ch222
加入factory机制
*/
top_tb.sv
`timescale 1ns/1ns
`include "uvm_macros.svh"
import uvm_pkg::*;
`include "my_driver.sv"
module top_tb ;
reg clk ; //时钟
reg rst_n ; //复位
reg [7:0] rxd ; //接受数据
reg rx_dv ; //接受数据
reg [7:0] txd ; //发送数据
reg tx_en ; //发送数据
dut my_dut(
.clk (clk ),
.rst_n (rst_n),
.rxd (rxd ),
.rx_dv (rx_dv),
.txd (txd ),
.tx_en (tx_en)
);
// initial begin
// my_driver drv;
// drv = new("drv",null);//传入数据
// drv.main_phase(null);
// $finish;
// end
initial begin
run_test("my_driver");
end
/*时钟模块*/
initial begin
clk = 0;
forever begin
#100ns clk = ~clk;
end
end
/*复位模块*/
initial begin
rst_n = 1'b0;
#1000;
rst_n = 1'b1;
end
/*fsdb*/
initial begin
$fsdbDumpfile("verilog.fsdb");
$fsdbDumpvars(0);
$display("fsdbDumpfilrs is start at %d",$time);
// #1e7;
// $finish;
end
endmodule
仿真结果
fsdbDumpfilrs is start at 0
--- UVM Report Summary ---
** Report counts by severity
UVM_INFO : 1
UVM_WARNING : 0
UVM_ERROR : 0
UVM_FATAL : 0
** Report counts by id
[RNTST] 1