如何通过+UVM_TESTNAME动态创建或覆盖UVM基准测试类?
Solution to UVM Test Name Precedence Issue
The core problem is that +UVM_TESTNAME takes priority over the argument passed to run_test(), so UVM will always attempt to instantiate the test class specified by +UVM_TESTNAME—even if it doesn't exist, and even if you explicitly call run_test("base_test"). Here's a direct fix using UVM factory overrides and configuration database:
Step-by-Step Implementation
1. Top-Level Module Code
Intercept the +UVM_TESTNAME value, check if the test class exists, and map non-existent test names to base_test while passing mode information:
module top; import uvm_pkg::*; `include "uvm_macros.svh" `include "base_test.svh" // Include existing test classes (e.g., test_mode2.svh) here if needed initial begin string uvm_testname; uvm_component_wrapper test_wrapper; // Extract the requested test name from +UVM_TESTNAME if ($value$plusargs("UVM_TESTNAME=%s", uvm_testname)) begin // Check if the test class exists in the UVM factory test_wrapper = uvm_factory::get().find_by_name(uvm_testname); if (test_wrapper == null) begin // Map non-existent test name to base_test uvm_factory::get().set_type_override_by_name(uvm_testname, "base_test"); // Pass test mode (from UVM_TESTNAME) to base_test via config DB uvm_config_db#(string)::set(null, "uvm_test_top", "test_mode", uvm_testname); // Optional: Extract mode from +arg if provided string mode_arg; if ($value$plusargs("arg=%s", mode_arg)) begin uvm_config_db#(string)::set(null, "uvm_test_top", "mode_arg", mode_arg); end end end // Run the test (uses +UVM_TESTNAME, with override if needed) run_test(); end endmodule
2. Base Test Code
Retrieve mode information from the config database and configure the appropriate sequence:
class base_test extends uvm_test; `uvm_component_utils(base_test) string test_mode; string mode_arg; function new(string name="base_test", uvm_component parent=null); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); // Get test mode from config DB (fallback to default if not set) if (!uvm_config_db#(string)::get(this, "", "test_mode", test_mode)) begin test_mode = "default_mode"; end // Get mode_arg if provided, else use test_mode as fallback if (!uvm_config_db#(string)::get(this, "", "mode_arg", mode_arg)) begin mode_arg = test_mode; end // Pass mode to sequences via config DB uvm_config_db#(string)::set(this, "*", "sequence_mode", mode_arg); // Add your testbench build logic here (env, agent, etc.) endfunction task run_phase(uvm_phase phase); phase.raise_objection(this); // Launch sequence based on selected mode case(mode_arg) "mode1": begin mode1_seq seq = mode1_seq::type_id::create("seq"); seq.start(env.agent.seqr); end "mode2": begin mode2_seq seq = mode2_seq::type_id::create("seq"); seq.start(env.agent.seqr); end default: begin default_seq seq = default_seq::type_id::create("seq"); seq.start(env.agent.seqr); end endcase phase.drop_objection(this); endtask endclass
How It Works for Your Cases
- Case 1 (Non-existent test class): When running
make run +UVM_TESTNAME=test_mode1 +arg=mode1, the factory detectstest_mode1doesn't exist, maps it tobase_test, and passes the mode values tobase_test. The base test then runs themode1sequence. - Case 2 (Existing test class): When running
make run +UVM_TESTNAME=test_mode2, the factory finds thetest_mode2class exists, so no override is applied. UVM runs thetest_mode2class as per standard UVM flow.
内容的提问来源于stack exchange,提问作者Siraj Mubarak
相关产品推荐
相关产品推荐

