UVm How It Work
UVm How It Work
Clifford E. Cummings
Tom Fitzpatrick
ABSTRACT
The Open Verification Methodology (OVM) and the new Universal Verification methodology (UVM) have a number of methods for
terminating the run() phase at the completion of a test, usually via a combination of sequence completion, calls to the global stop_request
mechanism and/or the recently-added objection mechanism. Many users also use built-in event and barrier constructs on a more
application-specific basis to achieve their goals. This plethora of choices has led to some confusion among the user community about how
best to manage this important aspect of the testbench.
This paper describes various techniques for gracefully terminating an OVM/UVM test, and proposes a set of guidelines to avoid further
confusion.
General Terms
Algorithms, Documentation, Performance, Design, Experimentation, Standardization, Languages, Theory, Verification.
Keywords
UVM, OVM, SystemVerilog, testbench, global_stop_request() , raise objection, drop objection.
1. INTRODUCTION
UVM is a verification class library based largely on the OVM version 2.1.1 class library. The descriptions in this paper reference the UVM
code and methods but the comments on this topic are just as applicable to OVM. Terminating the simulation run() phase is identical
using either class library except where noted.
Unlike all of the design modules and interfaces that are called during compilation and elaboration, none of the UVM testbench
environment is setup until after simulation starts.
To help understand these topics, it is often useful to understand some basics about how the UVM class library is laid out in the uvm
directory and file setup. This paper details important basics on vital files and how they are laid out. The location of important files, class
definitions and global variables and tasks can be difficult to find. This paper will help to partially navigate the UVM maze that hides many
important details.
1.1 Version
This paper is based on UVM version 1.0ea (ea - Early Adopter version), which is largely based on OVM version 2.1.1.
As shown in Figure 1, a design and testbench are first compiled, then the design and testbench are elaborated. Design and elaboration
happen before the start of simulation at time-0.
At time-0, the procedural blocks (initial and always blocks) in the top-level module and in the rest of the design start running. In the
top-level module is an initial block that calls the run_test() task from uvm_top. When run_test() is called at time-0, the
UVM pre-run() global function phases (build(), connect(), end_of_elaboration(), start_of_simulation()) all
execute and complete. After the pre-run() global function phases complete (still at time-0), the global run() phase starts. The run()
phase is a task-based phase that executes the entire simulation, consuming all of the simulation time. When the run() phase stops, the
UVM post-run() global function phases (extract(), check(), report() ) all run in the last time slot before simulation ends.
3. PHASES
For discussion purposes, it is useful to start with a quick reminder of the standard UVM phases. Some brief references will be made to
these phases throughout the content of this paper.
Some of the best UVM (and OVM) documentation is actually buried in the comments of the UVM base class source files themselves, if
you know where to look. A concise description of the UVM phases can be found in the uvm_phases.sv file in the uvm/src/base
subdirectory.
In fact, the following excellent summary-description of the UVM phases comes from comments on lines 284-316 of the
uvm_phases.sv file:
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
Section: Usage
Phases are a synchronizing mechanism for the environment. They are
represented by callback methods. A set of predefined phases and corresponding
callbacks are provided in uvm_component. Any class deriving from
uvm_component may implement any or all of these callbacks, which are executed
in a particular order. Depending on the properties of any given phase, the
corresponding callback is either a function or task, and it is executed in
top-down or bottom-up order.
The UVM provides the following predefined phases for all uvm_components.
build
connect
extract
check
report
Of these eight standard pre-defined phases, four of the phases are pre-run() function phases that execute in zero-time after compiling and
elaborating the design (typically at time-0) but before the run() phase commences, and three of the phases are post-run() function
phases that execute in zero-time at the end of the simulation after the run() phase completes.
termination of the run() phase allows the rest of the UVM post-run() function phases to do their intended jobs and then to terminate
gracefully.
Graceful termination of the run() phase often requires the use of UVM built-in termination commands, such as
global_stop_request(), and others described in this paper.
The run() phase is a time-consuming phase. The run() phase will unconditionally execute all of the run tasks, and conditionally all of
the stop tasks in the UVM testbench. run and stop are empty virtual tasks defined in the uvm_component. Any testbench
component that is derived from uvm_component can override the run and stop tasks and they will be executed during the run()
phase either unconditionally (run) or conditionally (stop).
Some of the common UVM components that are derived from uvm_component include:
Location: uvm/src/base/
uvm_root.svh:
class uvm_root
Location: uvm/src/methodology/
uvm_agent.svh:
uvm_driver.svh:
uvm_env.svh:
uvm_monitor.svh:
uvm_scoreboard.svh:
uvm_subscriber.svh:
uvm_test.svh:
virtual class
class
virtual class
virtual class
virtual class
virtual class
virtual class
uvm_agent
uvm_driver
uvm_env
uvm_monitor
uvm_scoreboard
uvm_subscriber
uvm_test
#( ... )
#( ... )
Location: uvm/src/methodology/sequences/
uvm_sequencer_base.svh:
class uvm_sequencer_base
Execution flow of the run and stop tasks in these stages is shown in the flow diagram of Figure 3.
If the thread with enable_stop_interrupt=1 does not include a local stop task, then the default empty stop() method will
execute and return in zero time.
As a general rule, threads that set the enable_stop_interrupt bit should also define a local stop task to override the default
stop() method. The authors can think of no good reason to set the enable_stop_interrupt bit and omit the inclusion of a local
stop task.
2.
Instantiates a Design Under Test (DUT) with design interface that is used to tie the class-based testbench to the DUT.
3.
Of course there is more to a UVM top-module than just these three pieces, but this will serve as a starting point.
What do we get when we import uvm_pkg::*; ?
The uvm_pkg.sv is located in the uvm/src directory and is little more than an `include command enclosed within a package as
shown in Example 2.
package uvm_pkg;
`include "uvm.svh"
endpackage
Example 2 - Abbreviated uvm_pkg.sv file
The included uvm.svh file itself includes global UVM macros, and calls on three more include files located in the uvm/base,
uvm/uvm_tlm and uvm/methodology subdirectories respectively as shown in Example 3.
//`include
`include
//`include
//`include
"uvm_macros.svh"
"base/base.svh"
"uvm_tlm/uvm_tlm.svh"
"methodology/methodology.svh"
Example 3 - Abbreviated uvm.svh file (with some `include files commented out)
In Example 3, we have commented out all of the include commands except for the "base/base.svh" include command, because we
are going to put together a simple example to show how some important UVM simulation commands are used.
The base.svh file actually includes 28 other files from the src/base subdirectory, but we are only going to focus on two of the
included files as shown in Example 4.
`include "base/uvm_component.sv"
//---------------------------------// uvm_component includes uvm_root
//---------------------------------`include "base/uvm_globals.svh"
Example 4 - Abbreviated base/base.svh file (shows inclusion of 2 of 28 included files)
The uvm/base subdirectory actually contains 39 files, but some of the files in this subdirectory include other files in the same
subdirectory. In fact, as indicated in Example 4, the uvm_component.sv file includes the very important uvm_root.svh file, which
is discussed next.
4.1 uvm_root
From comments in the uvm_root.svh source code file[11] (also in the ovm_root.svh source code file[8]):
"The uvm_root class serves as the implicit top-level and phase controller for all UVM components. Users do not directly instantiate
uvm_root. The UVM automatically creates a single instance of <uvm_root> that users can access via the global (uvm_pkg-scope)
variable, uvm_top. "
Among other things, the uvm_root.svh file, contains the uvm_root class definition, which is an extension of uvm_component.
uvm_root also has some very important methods and variables that are used at the beginning of the simulation. Important pieces of an
abbreviated uvm_root file with line numbers are shown in Example 5 and will be discussed in more detail in this section.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
run_global_phase();
endtask
task uvm_root::run_global_phase();
$display("run_global_phase() Phases now running");
endtask
//--------------------------------------------------------------------------// Stopping
//--------------------------------------------------------------------------function void uvm_root::stop_request();
// ->m_stop_request_e;
$display("Executing stop_request();");
endfunction
Example 5 - Abbreviated base/uvm_root.svh file
The uvm_root class includes the following important extern method definitions: protected function new(), get(),
run_test(), run_global_phase(), and stop_request().The external definitions are actually included later in the same file
(for example, the task uvm_root::run_test(...); definition starts on line 47). In fact all of the definitions for the extern
methods are actually defined later in the same file, which means they are not very extern-al! So why declare all of these methods as
extern methods? By declaring all of the methods as extern methods, the first 240 lines of the uvm_root.svh file serve as
documentation for and prototypes of the methods and important variables that make up the uvm_root non-virtual class. The details of
how the methods work are included in lines 266-1218 of the rest of this file. When you open the file, the top portion has an explanation of
what you will find in the uvm_root class and the bottom portion has the implementation details.
The uvm_root class also includes definitions for the time variables phase_timeout, stop_timeout and the static local
m_inst handle of type uvm_root.
This abbreviated version of uvm_root has been augmented with the function void uvm_rocks() method, which is not in the
actual uvm_root.svh file, but has been included in this abbreviated file for demonstration purposes as shown Example 6.
create a uvm_root object with handle name m_inst and return the handle to the calling code. All subsequent calls to get() will just
return the static m_inst handle value.
module test;
import uvm_pkg::*; // import uvm base classes
initial begin
uvm_top.uvm_rocks();
end
endmodule
Example 6 - Simple test module example that calls the uvm_top.uvm_rocks() method
19
20
21
The uvm_rocks() method shown in Example 7 is our simple replacement for the ubiquitous C-language "hello world" example (which
is so pass!)
A more typical usage example is a top-level module that calls a run_test() method as shown in Example 8.
module top;
import uvm_pkg::*; // import uvm base classes
initial begin
run_test();
end
endmodule
Example 8 - Top module example with run_test() call
4.3 run_test()
The run_test() method is also defined in the uvm_root class. Most initial block calls to run_test() do not reference this
method with the uvm_top handle name. Why does this work?
Now examine the base/uvm_globals.svh file. An abbreviated version of the uvm_globals.svh file is shown in Example 9.
The tasks and functions in the uvm_globals.svh file are also in the uvm_pkg, but they are not part of any class definition.
A call to run_test(), as shown in Example 8, calls the run_test() task defined in Example 9. The run_test() task declares a
handle called top of the uvm_root class type. Then the uvm_root::get() method is called, which will return the local static
uvm_root handle, m_inst, and store it into the top handle declared in the task (the uvm_root::get() method ensures that only
one uvm_root object will ever be created), and using the top handle, the local run_test() calls the top.run_test() method in
the uvm_top object, which starts up all the UVM simulation phases.
The uvm_globals.svh file also contains the set_global_timeout() and set_global_stop_timeout() methods, which
will be discussed in section 6.1.
As a side note, although not shown in the abbreviated version of the uvm_globals.svh file in Example 9, the uvm_globals.svh
file also contains the UVM standard message commands: uvm_report_info(), uvm_report_warning(),
uvm_report_error() and uvm_report_fatal(). These commands are also available anywhere the uvm_pkg routines have
been imported.
To summarize what has been discussed in this section, import uvm_pkg::*; creates the uvm_top module and includes important
global
commands
such
as
run_test(),
global_stop_request(),
set_global_timeout()
and
set_global_phase_timeout(). Users of the uvm_pkg have access to commands without being required to construct any class
objects.
module top;
...
initial begin
run_test("test1");
...
end
endmodule
The inline coded method is not typically recommended since it ties the testbench to a specific test that requires the top-module to be
modified, recompiled and simulated for each new test.
The +UVM_TESTNAME command line switch is the preferred method for executing tests since the simulation executable can be called with
a new testname without the requirement to re-compile the entire testbench. Below is shown an example command line switch using
Questa:
If the run_test() test name argument included in the top-module has not been registered in the UVM factory, or if the
+UVM_TESTNAME test name has not been registered in the UVM factory, then UVM reports the error shown in Figure 5.
module top;
import uvm_pkg::*;
logic
clk;
clkgen
ck (clk);
initial begin
run_task();
$finish;
end
task run_task;
uvm_report_info("top","run_task running");
#100ns;
endtask
endmodule
Example 10 - Verilog style testbench with task call followed by $finish
Since the uvm_pkg was imported in Example 10, the top module has access to the UVM reporting commands, which happened to be
called from the Verilog testbench run_task. Even though the uvm_pkg was imported, it was not necessary to call the UVM
run_test() command, so none of the UVM phases were executed, including the final reporting phase, and the final output simply
shows that UVM_INFO was called and that the top module finished at time 100ns, as shown in Figure 6.
module top;
import uvm_pkg::*; // import ovm base classes
import tb_pkg::*; // import testbench classes
logic
clk;
clkgen
ck (clk);
Runs all UVM phases so
initial begin
global_stop_request()
run_test();
will never execute
global_stop_request();
end
endmodule
Example 11 - BAD - top module with common mistake - global_stop_request() after run_test()
Engineers who assemble testing code as shown in Example 11 fail to understand that the run_test() command will execute all of the
UVM phases and the placement of the global_stop_request() command immediately after the run_test() command is too late
to be included in the execution of any of the UVM phases. In this example, the only call to global_stop_request() is placed in the
top-module, so the run_test() command will execute the requested run() phase test1 code, shown in Example 12 , then keep
executing simulation in the run() phase until simulation times out with the error message shown in Figure 7.
task run;
#100ns;
endtask
endclass
The test1 code of Example 12 was run with the top-module shown in Example 11, but since the test1 code did not include a
global_stop_request() command, and since the global_stop_request() command of the top module was never executed,
test1 executed its code and then the run() phase continued until the simulation timed-out.
Placement of a global_stop_request() command after a call to run_test() is a Verilog-like coding style that does not work in
UVM.
ck
clk;
(clk);
initial begin
run_test();
end
endmodule
Example 13 - GOOD - top module with run_test() and NO global_stop_request()
The top-module of Example 13 still includes the run_test() command, which is responsible for initiating and executing all of the
UVM phases.
After the test2 code of Example 14 terminates with global_stop_request(), the rest of the post-run() phases will execute (as
shown in Figure 8) and the full UVM report-output will be displayed as shown in Figure 9.
Figure 8 - global_stop_request() terminates the run() phase and post-run() phases execute
If the global_stop_request() command in the test code is replaced with the Verilog $finish command as shown in Example 15,
the simulation will abort in the middle of the run() phase and the post-run() phases will not execute as shown in Figure 10. Since the
UVM phases abort in the middle of the run() phase, no final UVM reports will be printed as can be seen in the resultant output in Figure
11.
class test2a extends uvm_test;
`uvm_component_utils(test2a)
env e;
function new (string name="test2a", uvm_component parent);
super.new(name, parent);
endfunction
function void build;
super.build();
e = env::type_id::create("e", this);
endfunction
task run;
#100ns;
$finish;
endtask
endclass
Example 15 - Bad - test2a terminates with $finish; - run() phase aborts early
Figure 10 - $finish command causes the run() phase to abort and post-run() phases never execute
In Figure 11, there is no UVM Report Summary because the post-run() report() phase was never executed.
run_test() - is a commonly used convenience function that calls uvm_top.run_test(). It is used to start the execution of the
specified test.
The basic UVM simulation termination command is the global_stop_request() call as previously shown in Example 14.
Two other ways to terminate simulations are timeouts and a combination of raised-objections and stop-interrupts.
6.1 Timeouts
When the run() phase starts, a parallel timeout timer is also started. If the timeout timer reaches one of the specified timeout limits
before the run() phase completes, the run() phase will timeout and:
1.
2.
3.
There are two timeout counters that may become active during the run() phase and their timeout limits are kept in the variables
uvm_top.phase_timeout and uvm_top.stop_timeout.
The phase_timeout is the time that the entire run() phase (Active Stage and Stop-Interrupt Stage) is allowed to run before timing
out. The phase_timeout is often referred to as the global_timeout limit as shown in Figure 12. If the phase_timeout time
limit is reached, a UVM_ERROR will be reported.
The default value for the phase_timeout limit is set from the `UVM_DEFAULT_TIMEOUT macro and has a default timeout value of
9200 seconds. This value can be shortened by using the set_global_timeout() command.
As part of the run() phase, various components of a test might execute stop tasks in the Stop-Interrupt Stage. The maximum execution
time of the stop tasks is stored in the stop_timeout limit and can be controlled by the set_global_stop_timeout()
command. The default stop_timeout value is also 9200 seconds. The stop_timeout is often referred to as the
global_stop_timeout limit as shown in Figure 12.
enable_stop_interrupt bit will be set (indicates that the test3 stop task should interrupt and execute its
code before the end of the run() phase.
Call the global_stop_request() command (causes end of Active Stage and start of Stop-Interrupt Stage) .
The printed messages and test3 UVM Report summary are shown in Figure 13. The first printed message came from the run_test()
command itself, the next two printed messages came from the stop task in Example 16, and the UVM Report Summary came from the
UVM report() phase at the end of the simulation.
The test in Example 16 executed the run task code in the Active Stage of the run() phase, while the stop task code executed in the
Stop-Interrupt Stage of the run() phase as shown in Figure 14.
Call the global_stop_request() command (causes end of Active Stage and start of Stop-Interrupt Stage) .
module top;
import uvm_pkg::*;
import tb_pkg::*;
logic
clkgen
ck
clk;
(clk);
initial begin
set_global_stop_timeout(50ns);
end
initial begin
run_test();
end
endmodule
Example 17 - top module - set_global_stop_timeout()
The printed messages are shown in Figure 15 (UVM Report summary not shown). The first printed message came from the run_test()
command itself, the next printed message came from the stop task in Example 18, and the UVM_WARNING timeout message came from
the phase execution mechanism in uvm_root. The UVM Report Summary (not shown) came from the UVM report() phase at the
end of the simulation.
The test4 example executed the run task code in the Active Stage and the stop task code in the Stop-Interrupt Stage before ending
early with a UVM stop_timeout warning also executed in the Stop-Interrupt Stage.
Call the global_stop_request() command (causes end of Active Stage and start of Stop-Interrupt Stage) .
module top;
import uvm_pkg::*;
import tb_pkg::*;
logic
clkgen
ck
clk;
(clk);
initial begin
set_global_stop_timeout(100ns);
set_global_timeout(550ns);
end
initial begin
run_test();
end
endmodule
Example 19 - top module - set_global_stop_timeout() & set_global_timeout()
The printed messages are shown in Figure 16 (UVM Report summary not shown). The first printed message came from the run_test()
command itself, the next printed message came from the stop task in Example 20, and the UVM_ERROR timeout message came from the
phase execution mechanism in uvm_root.
The test5 example executed the run task code in the Active Stage and the stop task code in the Stop-Interrupt Stage before ending
early with a UVM global_timeout error also executed in the Stop-Interrupt Stage.
Call the global_stop_request() command (causes end of Active Stage and start of Stop-Interrupt Stage) .
module top;
import uvm_pkg::*;
import tb_pkg::*;
logic
clkgen
ck
clk;
(clk);
initial begin
set_global_stop_timeout(100ns);
set_global_timeout(550ns);
end
initial begin
#100ns run_test();
end
endmodule
Example 21 - top module - set_global_stop_timeout(), set_global_timeout() and delayed startup
The printed messages are shown in Figure 17 (UVM Report summary not shown). The first printed message came from the run_test()
command itself at time 100ns, the next printed message came 500ns later from the stop task in Example 22, and the UVM_ERROR
timeout message came from the phase execution mechanism in uvm_root at time 650ns.
The test6 example did not start the run() phase and global_timeout counter until 100ns into the simulation, then test6 executed the
run task code in the Active Stage and the stop task code in the Stop-Interrupt Stage before ending early with a UVM global_timeout
error also executed in the Stop-Interrupt Stage.
Call the global_stop_request() command (causes end of Active Stage and start of Stop-Interrupt Stage) .
module top;
import uvm_pkg::*;
import tb_pkg::*;
logic
clkgen
ck
clk;
(clk);
initial begin
run_test();
end
endmodule
Example 23 - Simple top module used for testing - no timeout values set and no startup delays
The printed messages are shown in Figure 18 (UVM Report summary not shown). The first printed message came from the run_test()
command itself, the next printed message came 500ns later from the stop task in Example 24, and the UVM_WARNING timeout message
came from the phase execution mechanism in uvm_root at time 600ns.
The test7 example shows that the global_timeout limit must be set before executing the run task, otherwise the setting will be too late
and the global timeout counter will not start.
test8 executes:
build() phase starts at time 0ns.
Call the global_stop_request() command (causes end of Active Stage and start of Stop-Interrupt Stage) .
The printed messages are shown in Figure 19 (UVM Report summary not shown). The first printed message came from the run_test()
command itself, the next printed message came 500ns later from the stop task in Example 25, and the UVM_ERROR timeout message
came from the phase execution mechanism in uvm_root at time 550ns.
The test8 example shows that the global_timeout limit can be properly set in the build() phase, before executing the run task in the
run() phase. Although this style works, this is not necessarily a recommended coding style.
test9 executes:
run() phase starts at time 0ns (start of Active Stage).
Call the uvm_test_done.drop_objection() command. All objections have been dropped because there was
only one objection (causes implicit call to global_stop_request()), which causes the end of the Active Stage
and start of Stop-Interrupt Stage) .
The printed messages are shown in Figure 20 (UVM Report summary not shown). The first printed message came from the run_test()
command itself, the next printed message came 500ns later and is the TEST_DONE message, which shows that the dropping of all
objections has forced an implicit call to the global_stop_request() command.
The test9 example shows that after all objections have been dropped that there is an implicit call to the global_stop_request()
command, which will terminate the Active Stage of the run() phase.
Later tests will show that any active Objections-Raised threads will take control of when the Active Stage completes.
test10 executes:
run() phase starts at time 0ns (start of Active Stage).
All objections have now been dropped (causes implicit call to global_stop_request()), which causes the end
of the Active Stage and start of Stop-Interrupt Stage) .
The printed messages are shown in Figure 21 (UVM Report summary not shown). The first printed message came from the run_test()
command itself, the next printed message came 700ns later and is the TEST_DONE message, which shows that the dropping of all
objections has forced an implicit call to the global_stop_request() command.
The test10 example shows that after all objections have been dropped that there is an implicit call to the global_stop_request()
command, which will terminate the Active Stage of the run() phase.
test11 executes:
run() phase starts at time 0ns (start of Active Stage).
forever-loop cycles every 120ns and prints a repeating message. The forever-loop keeps running until the
run() phase finishes.
All objections have now been dropped (causes implicit call to global_stop_request()), which causes the end
of the Active Stage and start of Stop-Interrupt Stage) .
The printed messages are shown in Figure 22 (UVM Report summary not shown). The first printed message came from the run_test()
command itself. The next six printed messages came at 120ns intervals from the tb_driver component. The next printed message came
811ns after the start of the Active Stage and is the TEST_DONE message, which shows that the dropping of all objections has forced an
implicit call to the global_stop_request() command, even though the forever loop continued to run.
The test11 example shows that after all objections have been dropped that there is an implicit call to the global_stop_request()
command, which will terminate the Active Stage of the run() phase, even if there was a forever loop running in another run task.
test12 executes:
run() phase starts at time 0ns (start of Active Stage).
forever-loop cycles every 120ns and prints a repeating message. The forever-loop keeps running throughout the
Stop-Interrupt Stage.
All objections have now been dropped (causes implicit call to global_stop_request()), which causes the end
of the Active Stage and start of Stop-Interrupt Stage) .
The printed messages are shown in Figure 23 (UVM Report summary not shown). The first printed message came from the run_test()
command itself. The next six printed messages came at 120ns intervals from the tb_driver component. The next printed message came
811ns after the start of the Active Stage and is the TEST_DONE message, which shows that the dropping of all objections has forced an
implicit call to the global_stop_request() command, even though the forever loop continued to run. The next message came
from the tb_driver stop task while the tb_driver run task continued to execute the forever loop. The next nine printed
messages continued to come at 120ns intervals from the tb_driver component, while the last printed message came from the
tb_driver stop task just before the Stop-Interrupt Stage finished.
The test12 example shows that after all objections have been dropped that there is an implicit call to the global_stop_request()
command, which will terminate the Active Stage of the run() phase, even if there was a forever loop running in another run task. It
also shows that even though test12 entered the Stop-Interrupt Stage for the next 1,000ns, that the run task forever loop continued to
run throughout the Stop-Interrupt stage. It can be seen that not all run tasks have to finish before the Stop-Interrupt Stage activity can
commence.
test13 executes:
run() phase starts at time 0ns (start of Active Stage).
forever-loop cycles every 120ns and prints a repeating message. The forever-loop keeps running throughout the
Active Stage.
All objections have now been dropped (causes implicit call to global_stop_request()), which causes the end
of the Active Stage and start of Stop-Interrupt Stage) .
The printed messages are shown in Figure 24 (UVM Report summary not shown). The first printed message came from the run_test()
command itself. The next six printed messages came at 120ns intervals from the tb_driver component. The next printed message came
811ns after the start of the Active Stage and is the TEST_DONE message, which shows that the dropping of all objections has forced an
implicit call to the global_stop_request() command, even though the forever loop continued to run. NOTE: there was a call to
global_stop_request() at 100ns, but the command was ignored until all objections were dropped. The final message makes
reference to the "Previous call to global_stop_request()," which is "now (being) honored."
The test13 example shows that explicit calls to global_stop_request() are ignored if there are any raised objections. Only after
all objections have been dropped is there an implicit call to the global_stop_request() command, which will terminate the Active
Stage of the run() phase.
test14 executes:
run() phase starts at time 0ns (start of Active Stage).
Calls the global_stop_request() command at 1,000ns (too late - run() phase has already completed)
forever-loop cycles every 120ns and prints a repeating message. The forever-loop keeps running throughout the
Active Stage.
All objections have now been dropped (causes implicit call to global_stop_request()), which causes the end
of the Active Stage and start of Stop-Interrupt Stage) .
The printed messages are shown in Figure 25 (UVM Report summary not shown). The first printed message came from the run_test()
command itself. The next six printed messages came at 120ns intervals from the tb_driver component. The next printed message came
811ns after the start of the Active Stage and is the TEST_DONE message, which shows that the dropping of all objections has forced an
implicit call to the global_stop_request() command, even though the forever loop continued to run. NOTE: there was a call to
global_stop_request() at 1,000ns, but the command came after the run() phase had finished.
The test14 example shows that after all objections have been dropped there is an implicit call to the global_stop_request()
command, which will terminate the Active Stage of the run() phase.
8. ACKNOWLEDGMENTS
Our thanks to our colleague Kelly Larson for sharing useful comments and feedback during the development of this paper. Also thanks to
our colleague Mike Horn for sharing important information related to the use of the run_test() command.
9. REFERENCES
[1] "IEEE Standard For SystemVerilog - Unified Hardware Design, Specification and Verification Language," IEEE Computer Society,
IEEE, New York, NY, IEEE Std 1800-2009. http://standards.ieee.org/findstds/standard/1800-2009.html
[2] Mark Glasser, "Open Verification Methodology Cookbook", Springer, www.springeronline.com, 1st Edition., 2009. ISBN: 978-14419-0967-1
Free PDF Version at: http://verification-academy.mentor.com/content/open-verification-methodology-advanced-ovm-uvm-module
[3] Mentor Graphics Corp. 10 Dec 2010. EOT/Guide. http://uvm.mentor.com/mc/EOT/ovm_test_done
[4] Mentor Graphics Corp. 28 Feb 2011. UVM/OVM Methodology Cookbook. http://uvm.mentor.com/uvm/EOT/Guide
[5] Mike Horn - personal communication.
[6] OVM Class Reference, Version 2.1.1, March 2010. In OVM source code: ovm-2.1.1/OVM_Reference.pdf
[7] OVM 2.1.1 kit - includes OVM base class libraries - Free downloads - www.ovmworld.org (choose Download).
[8] ovm-2.1.1/src/base/ovm_root.svh - comments in the source code file.
[9] Universal Verification Methodology (UVM) 1.0 EA Class Reference, May 2010, Accellera, Napa, CA. In UVM source code:
uvm1.0ea/uvm_reference_guide_1.0_ea.pdf
[10] UVM 1.0EA (Early Adopter) kit - includes UVM base class libraries - Free downloads - www.uvmworld.org (choose Download).
[11] uvm1.0ea/src/base/uvm_root.svh - comments in the source code file.
Tom Fitzpatrick, Verification Technologist and Editor of Verification Horizons at Mentor Graphics. Design and verification expert using
SystemVerilog; developing, educating and writing about industry standards.
Email address: [email protected]
An updated version of this paper can be downloaded from the web sites:
www.sunburst-design.com/papers