验证环境构建起了各种激励释放,监控和积分的总体架构,是一个统筹全局的模块,负责将验证部分打包起来。
`ifndef ENV `define ENV class environment; virtual alu_interface intf; virtual alu_reg_interface reg_intf; virtual apb_interface apb_intf; generator gen; driver drv; monitor mon; scoreboard scb; coverage cov; mailbox gen2drv; mailbox mon2scb; mailbox mon2cov; function new (virtual alu_interface intf_new, virtual apb_interface apb_intf_new, virtual alu_reg_interface reg_intf_new); this.intf = intf_new; this.apb_intf = apb_intf_new; this.reg_intf = reg_intf_new; endfunction function void build(); $display("%0t -> environment : start build() method",$time); gen2drv = new(); mon2scb = new(); mon2cov = new(); gen = new(gen2drv); drv = new(intf, apb_intf, gen2drv); mon = new(intf, reg_intf, mon2cov, mon2scb); scb = new(reg_intf, mon2scb); cov = new(mon2cov); $display("%0t -> environment : finish build() method",$time); endfunction task reset(); $display("%0t -> environment : start reset() method",$time); begin logic[15:0] alu_result; transaction tr = new(); tr.op = rst_op; this.intf.send_op(tr,alu_result); end $display("%0t -> environment : finish reset() method",$time); endtask task config(); #100; $display("%0t -> environment : start config() method",$time); begin data_t data; addr_t addr; addr = `ALU_BEGIN_ADDR + `BASE_ADDR + `CFG_CTRL_REG_OFFSET; data[`CFG_CTRL_REG_SIZE-1:0] = 1'd1; apb_intf.master_write(addr,data); $display("%0t -> write CFG_CTRL_REG value : %0h",$time,data); apb_intf.master_read(addr,data); $display("%0t -> read CFG_CTRL_REG value : %0h",$time,data); end $display("%0t -> environment : finish config() method",$time); endtask task start(); $display("%0t -> environment : start start() method",$time); fork gen.run(); drv.run(); mon.run(); cov.run(); scb.run(); join_none $display("%0t -> environment : finish start() method",$time); endtask task wait_finish(); $display("%0t -> environment : start wait_finish() method",$time); repeat(10000) @(posedge intf.clk); $display("%0t -> environment : finish wait_finish() method",$time); endtask task report(); $display("%0t -> environment : start report() method",$time); $display("\n"); if(scb.fail_cnt == 0)begin $display("************ Test PASSED ***************"); $display("************ total: %0d ***************",mon.total_cnt); $display("************ pass: %0d fail: 0 ***************",scb.pass_cnt); end else begin $display("************ Test FAIL ***************"); $display("************ total: %0d ***************",mon.total_cnt); $display("************ pass: %0d fail: %0d ***************",scb.pass_cnt,scb.fail_cnt); end $display("coverage op_cov: %g%%, zeros_or_ones_on_ops: %g%%",cov.op_cov.get_coverage(),cov.zeros_or_ones_on_ops.get_coverage()); $display("\n"); $display("%0t -> environment : finish report() method",$time); endtask task run(); $display("%0t -> environment : start run() method",$time); build(); reset(); config(); start(); wait_finish(); report(); $display("%0t -> environment : finish run() method",$time); endtask endclass `endif
模块引入
在这里我们可以看到几个重点位置,
virtual alu_interface intf; virtual alu_reg_interface reg_intf; virtual apb_interface apb_intf; generator gen; driver drv; monitor mon; scoreboard scb; coverage cov; mailbox gen2drv; mailbox mon2scb; mailbox mon2cov;
这里就把所有的验证模块都打包进来了。
new的使用
有一个很关键的地方,也是用来学习
new
的使用的关键位置,就是://构造函数 function new (virtual alu_interface intf_new, virtual apb_interface apb_intf_new, virtual alu_reg_interface reg_intf_new); this.intf = intf_new; this.apb_intf = apb_intf_new; this.reg_intf = reg_intf_new; endfunction //类的实例化 gen2drv = new();
理解这两个位置的用法对掌握
new
的使用这个知识点具有关键作用。首先,function new(…);
是标准意义上的构造函数,用来对类里的某些参数进行初始化;gen2drv = new();
则是一个对类的实例化。二者是怎么用的呢?function new(…);
这种用法一般用在一个类的内部,就是在声明一个类时,用这个方法来对某些参数进行初始化。当然,并不是要求对所有的类都要应用这一点,我们也可以不显式的声明new
,这时程序自动默认进行了构造。
gen2drv = new();
这种用法一般用在类的外部,就是在别的地方要使用一个类时,我们必须显式的调用new
来声明它,否则我们是无法使用这个类的。