UVM Test

The top-level component that instantiates the environment and starts sequences.

The Orchestrator Role

What is the Test Class?

The Simple Version: The Test is the "director" of your verification. It sets up the environment, configures how things should behave, and starts the simulation.

Think of it like: A movie director. The Test decides what the scene looks like (environment setup), how actors should behave (configuration), and when to start filming (run the test).

The uvm_test class is the "Brain" of the verification environment. While other components (Drivers, Monitors) are fixed in their structure, the Test is dynamic—it decides which environment to build, how to configure it, and what stimulus to apply.

1. The base_test Pattern

In the real world, you don't write a brand new test from scratch every time. Instead, you create a Base Test. This is your "Template". It sets up the boring stuff (clock, reset, standard environment). Then, for your actual tests, you just copy (extend) this Base Test and add the special sauce for that specific scenario.

Pro Tip:
  • Base Test: The foundation. Has connection code, timeout settings, and default config.
  • Derived Test: The specific test. "Base Test + Error Injection" or "Base Test + Long Delay".
Example: Professional Base Test

class base_test extends uvm_test;
    `uvm_component_utils(base_test)
    my_env env;
    function void build_phase(uvm_phase phase);
        // Create the environment using the factory
        env = my_env::type_id::create("env", this);
        // Pass standard configurations to the agents
        uvm_config_db#(int)::set(this, "env.agt*", "is_active", UVM_ACTIVE);
    endfunction
    // Catch-all timeout for safety
    function void start_of_simulation_phase(uvm_phase phase);
        uvm_top.set_timeout(1ms);
    endfunction
endclass
                            

Dynamic Variation: Overrides

A derived test leverages factory overrides to change the behavior of sub-components without touching the structural code of the environment.

Example: Error Injection Test

class err_inj_test extends base_test;
    `uvm_component_utils(err_inj_test)
    function void build_phase(uvm_phase phase);
        // Step 1: Request the factory to swap the standard driver
        // This MUST happen before super.build_phase()!
        my_driver::type_id::set_type_override(error_driver::get_type());
        // Step 2: Now call base build (which creates the env)
        super.build_phase(phase);
    endfunction
endclass
                            

Stimulus Control

The Test is responsible for starting sequences. This is typically done in the run_phase using the start() method on the sequencer handle.


task run_phase(uvm_phase phase);
    my_seq seq = my_seq::type_id::create("seq");
    phase.raise_objection(this, "Starting Main Stimulus");
    seq.start(env.agt.sqr);
    phase.drop_objection(this, "Stimulus Finished");
endtask
                            

Command Line execution

To run your simulation with a specific test, use the following simulator switch:

+UVM_TESTNAME=err_inj_test