《UVM Primer》第11章代码示例编译报错修复方案咨询
修复《UVM Primer》第11章代码的编译错误
我来帮你逐个拆解并解决这些编译报错,问题核心是书中代码混淆了UVM测试组件和激励生成类的结构,再加上构造函数参数传递错误导致的:
错误原因逐一分析
1. 构造函数参数不匹配(错误1、2、4、5)
你定义的random_tester继承了uvm_test,它的构造函数要求传入string name和uvm_component parent两个参数,但你在run_phase里用random_tester_h = new(bfm);调用时,直接把virtual interface传给了需要字符串类型的name参数,还漏掉了parent参数,这就同时触发了类型不匹配和参数缺失的错误。
更关键的问题是:random_tester不应该是uvm_test的子类。UVM的uvm_test是顶层测试组件,而负责生成激励的tester应该是一个独立的普通类,它的构造函数只需要接收virtual interface,不需要UVM组件的构造参数。
2. 缺少execute方法定义(错误3、6)
你的random_tester类里根本没有定义execute任务,编译器自然找不到这个方法。这是因为你错误地把激励生成逻辑和UVM测试组件的逻辑混在了同一个类里。
修复后的完整代码
1. 修正tinyalu_pkg.sv
我们需要把tester类和UVM测试类拆分,先定义独立的激励生成类,再定义顶层UVM测试类:
// FILE: tinyalu_pkg.sv package tinyalu_pkg; import uvm_pkg::*; `include "uvm_macros.svh" typedef enum bit[2:0] { no_op = 3'b000, add_op = 3'b001, and_op = 3'b010, xor_op = 3'b011, mul_op = 3'b100, rst_op = 3'b111 } operation_t; typedef struct { byte unsigned A; byte unsigned B; operation_t op; } command_s; // 独立的随机激励生成类,负责驱动BFM class random_tester; virtual tinyalu_bfm bfm; // 构造函数接收virtual interface function new(virtual tinyalu_bfm bfm); this.bfm = bfm; endfunction : new // 定义execute任务,实现激励生成逻辑(补充书中缺失的代码) task execute(); // 先复位DUT bfm.reset_n = 1'b0; #10 bfm.reset_n = 1'b1; // 生成10组随机激励 repeat(10) begin bfm.A = $urandom_range(0,255); bfm.B = $urandom_range(0,255); bfm.op = operation_t'($urandom_range(0,5)); bfm.start = 1'b1; wait(bfm.done); bfm.start = 1'b0; #5; end endtask : execute endclass // 真正的UVM顶层测试类 class random_test extends uvm_test; `uvm_component_utils(random_test); virtual tinyalu_bfm bfm; // UVM组件标准构造函数 function new (string name, uvm_component parent); super.new(name,parent); endfunction : new // 在build_phase中获取config_db的BFM(UVM标准做法) function void build_phase(uvm_phase phase); super.build_phase(phase); if(!uvm_config_db #(virtual tinyalu_bfm)::get(this, "", "bfm", bfm)) $fatal("Failed to get BFM from config_db"); endfunction : build_phase task run_phase(uvm_phase phase); random_tester random_tester_h; //coverage coverage_h; //scoreboard scoreboard_h; phase.raise_objection(this); // 实例化tester类,传入bfm random_tester_h = new(bfm); //coverage_h = new(bfm); //scoreboard_h = new(bfm); //fork // coverage_h.execute(); // scoreboard_h.execute(); //join_none random_tester_h.execute(); phase.drop_objection(this); endtask : run_phase endclass // 同理修复add_test类 class add_tester; virtual tinyalu_bfm bfm; function new(virtual tinyalu_bfm bfm); this.bfm = bfm; endfunction : new task execute(); bfm.reset_n = 1'b0; #10 bfm.reset_n = 1'b1; repeat(10) begin bfm.A = $urandom_range(0,255); bfm.B = $urandom_range(0,255); bfm.op = add_op; // 固定为加法操作 bfm.start = 1'b1; wait(bfm.done); bfm.start = 1'b0; #5; end endtask : execute endclass class add_test extends uvm_test; `uvm_component_utils(add_test); virtual tinyalu_bfm bfm; function new (string name, uvm_component parent); super.new(name,parent); endfunction : new function void build_phase(uvm_phase phase); super.build_phase(phase); if(!uvm_config_db #(virtual tinyalu_bfm)::get(this, "", "bfm", bfm)) $fatal("Failed to get BFM from config_db"); endfunction : build_phase task run_phase(uvm_phase phase); add_tester add_tester_h; phase.raise_objection(this); add_tester_h = new(bfm); add_tester_h.execute(); phase.drop_objection(this); endtask : run_phase endclass endpackage : tinyalu_pkg
2. 保留top.sv不变
你的top.sv代码没有问题,可以直接使用。
编译验证
修改完成后,重新用QuestaSim编译:
vlog -work work .\hdl\tinyalu_pkg.sv .\hdl\top.sv
所有6个编译错误应该都能解决。
内容的提问来源于stack exchange,提问作者pico
相关产品推荐
相关产品推荐

