SystemVerilog Verification
Using
UVM 1.0
VCS 2011.03
Synopsys Customer Education Services
2011 Synopsys, Inc. All Rights Reserved
Synopsys 40-I-054-SSG-001
Introductions
n
Name
Company
Job Responsibilities
EDA Experience
Main Goal(s) and Expectations for this Course
Facilities
Building Hours
Emergency
Phones
EXIT
Messages
Restrooms
Smoking
Meals
Recycling
Please turn off cell phones and pagers
3
Course Materials
n
Student Workbook
Lab Book
Reference Materials
Course Evaluations
Workshop Goal
Acquire the skills to implement a UVM testbench to verify
Verilog/VHDL designs with coverage-driven random stimulus
Target Audience
Design or Verification engineers
writing SystemVerilog testbenches
to verify Verilog or VHDL designs
Workshop Prerequisites
n
You should have experience in the following areas:
l
l
l
Familiarity with a UNIX text editor
Programming skills in SystemVerilog
Debugging experience with SystemVerilog
Agenda: Day 1
DAY
1
OOP Inheritance Review
UVM Overview
Modeling Transactions
Creating Stimulus Sequences
Agenda: Day 2
DAY
2
Component Configuration & Factory
TLM Communication
Scoreboard & Coverage
UVM Callback
Agenda: Day 3
DAY
3
Sequence Library/Virtual Sequencer
10
More on Phasing
11
Register Abstraction Layer
12
Summary
10
What Is the Device Under Test?
A router:
16 x 16 crosspoint switch
din [15:0]
dout [15:0]
frame_n[15:0]
valid_n [15:0]
frameo_n [15:0]
router
valido_n [15:0]
reset_n
clock
11
A Functional Perspective
frame_n[0]
valid_n[0]
din[0]
inputs
outputs
port
port
0
frameo_n[0]
valido_n[0]
dout[0]
partial view
12
The Router Description
n
Single positive-edge clock
Input and output data are serial (1 bit / clock)
Packets are sent through in variable length:
l
Each packet is composed of two parts
Header
u Payload
u
Packets can be routed from any input port to any
output port on a packet-by-packet basis
No internal buffering or broadcasting (1-to-N)
13
Input Packet Structure
n
frame_n:
l
l
din:
l
Falling edge indicates first bit of packet
Rising edge indicates last bit of packet
Header (destination address & padding bits) and payload
valid_n:
l
valid_n is low if payload bit is valid, high otherwise
clock
din[i]
A0
A1
A2
A3
valid_n[i]
d0
....
x dn-2 dn-1
frame_n[i]
dest. address
pad
payload
14
Output Packet Structure
n
n
Output activity is indicated by:
frameo_n, valido_n, and dout
Data is valid only when:
l
l
frameo_n output is low (except for last bit)
valido_n output is low
Header field is stripped
clock
dout[i]
valido_n[i]
d0
d1
d2
d3
dn-3
x dn-2 dn-1
x
x
frameo_n[i]
15
Reset Signal
n
While asserting reset_n, frame_n and valid_n
must be de-asserted
reset_n is asserted for at least one clock cycle
After de-asserting reset_n, wait for 15 clocks
before sending a packet through the router
clock
reset_n
frame_n[i]
valid_n[i]
15 clock cycles
16
Icons Used in this Workshop
Lab Exercise
Caution
Recommendation
Definition of
Acronyms
For Further Reference
Question
Under the Hood
Information
Group Exercise
17
18
Agenda: Day 1
DAY
1
OOP Inheritance Review
UVM Overview
Modeling Transactions
Creating Stimulus Sequences
19
Unit Objectives
After completing this unit, you should be able to:
n
Use OOP inheritance to create new OOP classes
Use Inheritance to add new properties and
functionalities
Override methods in existing classes with
inherited methods using virtual methods and
polymorphism
20
Object Oriented Programming: Classes
n
Object-oriented programming
l
l
"class"
Vera, e, C++, SystemVerilog
Data and procedures together
Properties need not
be passed as arguments
class Packet
da
sa
data
function void display();
...
endfunction
crc
function int compute_crc();
...
endfunction
Data & procedures
encapsulated
Packet pkt = new();
[Link] = pkt.compute_crc();
[Link]();
21
Object Oriented Programming: Inheritance
n
Object-oriented programming
l
l
New classes derived from original (base) class
Inherits all contents of base class
class BadPacket extends Packet
da
sa
Packet
data
crc
BadPacket
bad
function void display();
...
endfunction
function int compute_crc();
...
endfunction
Packet
BadPacket
UML
Can override
methods
in base class
function int compute_crc();
[Link] = super.compute_crc();
if (bad) crc = ~crc;
Can call overridden
endfunction
behavior
22
Object Oriented Programming: Inheritance
n
Derived classes compatible with base class
l
Can reuse code
Base class
Packet pkt = new();
transmit(pkt);
Packet
BadPacket bad_pkt = new();
transmit(bad_pkt);
Use
$cast()
Compatible
BadPacket
Compatible
task transmit(Packet pkt);
...
endtask
Derived class
OK
pkt = bad_pkt;
Error
bad_pkt = pkt;
OK
$cast(bad_pkt, pkt);
23
OOP: Polymorphism
n
Which method gets called?
[Link] = p.compute_crc();
p
class BadPacket extends Packet
da
sa
data
crc
bad
function int compute_crc();
...
endfunction
function int compute_crc();
...
endfunction
Depends on
l
l
Type of handle p (e.g. Packet or BadPacket ?)
Whether compute_crc() is virtual or not
24
OOP: Polymorphism
n
If compute_crc() is not virtual
p
class BadPacket extends Packet
da
sa
data
crc
bad
function int compute_crc();
...
endfunction
function int compute_crc();
...
endfunction
Packet p = new();
BadPacket bp = new();
[Link] = p.compute_crc();
[Link] = bp.compute_crc();
transmit(p);
transmit(bp);
task transmit(Packet pkt);
[Link] = pkt.compute_crc();
...
endtask
25
OOP: Polymorphism
n
If compute_crc() is virtual
p
class BadPacket extends Packet
da
sa
data
crc
bad
virtual
function int compute_crc();
...
endfunction
virtual
function int compute_crc();
...
endfunction
Packet p = new();
BadPacket bp = new();
[Link] = p.compute_crc();
[Link] = bp.compute_crc();
transmit(p);
transmit(bp);
task transmit(Packet pkt);
[Link] = pkt.compute_crc();
...
endtask
26
OOP: Polymorphism
n
Trying to inject errors
protocol bfm = new(...);
repeat (100) begin
BadPacket bp = new();
[Link](bp);
end
pkt
class protocol;
class BadPacket extends packet
...
virtual task transmit(Packet pkt);
compute_crc()
[Link] = pkt.compute_crc();
...
If
compute_crc()
endtask
virtual
endclass
Guideline: methods should
be virtual
Can inject CRC errors
without modifying original code
27
Unit Objectives Review
You should now be able to:
n
Use OOP inheritance to create new OOP classes
Use Inheritance to add new properties an
functionalities
Override methods in existing classes with
inherited methods using virtual methods and
polymorphism
28
Appendix
Parameterized Class
Typedef Class
External Definition
Static Property and Method
Singleton Classes
Proxy Classes
29
Parameterized Classes
n
Written for a generic type
l
Type parameter passed at instantiation, just like
parameterized modules
Allows reuse of common code
program automatic test;
stack #(bit[31:0]) addr_stack;
pkt_stack;
stack #(packet)
initial begin
...
repeat(10) begin
packet pkt = new();
if(![Link]())
$finish;
[Link] = addr_stack.pop();
pkt_stack.push(pkt);
end
end
endprogram: test
class stack #(type T = int);
local T items[$];
function void push( T a );
...
function T pop( );
function int size(); ...
endclass: stack
30
typedef
n
Often need to use a class before declaration
l
e.g. two classes need handle to each other
typedef class S2;
class S1;
S2 inside_s1;
...
endclass: S1
This is a compile error
if typedef is missing
class S2;
S1 i_am_inside;
...
endclass: S2
Or, to simplify parameterized class usage
typedef stack #(bit[31:0]) stack32;
stack_pkt;
typedef stack #(packet)
program automatic test;
stack32
addr_stack;
stack_pkt
data_stack;
31
Methods Outside of the Class
n
The body of the class should fit on one screen
l
Show the properties, and method headers
Method bodies can go later in the file
l
Scope resolution operator :: separates class and method
name
class packet;
int da, sa, data[], crc;
extern virtual function void display(string prefix=);
extern virtual function int compute_crc();
endfunction
function void packet::display(string prefix=);
...
endfunction
function int packet::compute_crc();
...
endfunction
32
Static Property
n
How do I create a variable shared by all objects of a
class, but not make a global?
A static property is associated with the class
definition, not the object.
l
Can store meta-data, such as number of instances
constructed
Shared by all objects of that class
class packet;
static int count = 0;
int id;
function new();
id = count++;
endfunction
endclass
Using a id field can
help keep track of
transactions as they
flow through test
33
Static Method
n
Call a method without a handle
Can only access static properties
class packet;
static int count = 0;
int id;
static function void print_count();
$display(Created %0d packets, count);
endfunction
endclass
function void test::end_of_test();
packet::print_count();
...
endfunction
34
Singleton Classes
n
Used to define a global activity such as printing
or class factory
Only one instance of the singleton class exists
Contains only static properties and methods
class print;
static int err_count = 0, max_errors = 10;
static function void error (string msg);
$display(@%t: ERROR %s, $realtime, msg);
if (err_count++ > max_errors)
$finish;
endfunction
endclass
if (expect != actual)
print::error(Actual did not match expected);
35
Simple Proxy Class
n
Provides universal service routines like create()
class proxy_class#(type T=base);
typedef proxy_class#(T) this_type;
static this_type me = get();
// for coding convinience (not required)
// construct a static object of this proxy
// type at beginning of simulation
static function this_type get();
if (me == null) me = new(); return me;
endfunction
static function T create();
create = new(); class myclass extends base;
endfunction
typedef proxy_class#(myclass) proxy;
endclass
endclassclass anotherclass extends base;
typedef proxy_class#(anotherclass) proxy;
endclass
class environment;
myclass m_obj; anotherclass a_obj;
function new();
m_obj = myclass::proxy::create();
a_obj = anotherclass::proxy::create();
endfunction
endclass
36
Proxy Classes & Factory (1/5)
n
To create factory, two proxy class layers are needed:
l
l
l
Virtual proxy base class (this slide)
Proxy class (in a up coming slide)
Act as molds in factory
Virtual proxy wrapper class
l
l
Base proxy class type to enable OOP polymorphism
Declares abstracted interface methods for proxy services
Creating objects
u Get type name
u
virtual class proxy_base;
virtual function base create_object(string type_name);
return null;
endfunction
pure virtual function string get_typename();
endclass
37
Proxy Classes & Factory (2/5)
Factory class
n Provide creation of object on demand
n Maintain a registry of proxy objects
class factory;
static proxy_base registry[string];
static factory me = get();
static function factory get();
if (me == null) me = new(); return me;
endfunction
function void register(proxy_base proxy);
registry[proxy.get_typename()] = proxy;
endfunction
function base create_object_by_type(proxy_base proxy, string name);
proxy = find_override(proxy);
return proxy.create_object(name);
endfunction
// continued on next slide
38
Creating Proxy Classes & Factory (3/5)
Factory class continued
n
Maintains a registry of proxies to be replaced with
overridden proxies
l
If overridden, creates overridden objects
static string override[string];
Original proxy type
static function void override_type(string type_name,override_typename);
override[type_name] = override_typename;
To be replaced by overridden
endfunction
proxy
function proxy_base find_override(proxy_base proxy);
if ([Link](proxy.get_typename()))
return registry[override[proxy.get_typename()]];
return proxy;
endfunction
endclass
39
Creating Proxy Classes & Factory (4/5)
n
Proxy class
l
l
l
Implements the abstracted interface methods
Registers itself in factory
Create object using factory
class proxy_class#(type T=base, string Tname="none") extends proxy_base;
typedef proxy_class#(T, Tname) this_type; // for coding convinience (not
required)
static string type_name = Tname;
static this_type me = get();
static function this_type get();
factory f = factory::get(); if (me == null) me = new();
[Link](me);
return me;
Use factory to create
endfunction
object
static function T create(string name);
factory f = factory::get();
$cast(create, f.create_object_by_type(me, name));
endfunction
virtual function base create_object(string name);
T object_represented = new(name);
return object_represented;
endfunction
endclass
40
Creating Proxy Classes & Factory (5/5)
Why go through all these trouble?
n Test can use factory to override any object created
in environment without touching environment class
class modified extends myclass;
typedef proxy_class#(modified, "modified") proxy;
// other code not shown
endclass
program automatic test;
environment env;
initial begin
factory::override_type("myclass", "modified");
env = new();
// other code not shown
end
The override will cause a
class environment;
myclass m_obj; anotherclass a_obj;
modified class object to be
function new();
created instead of myclass
m_obj = myclass::proxy::create();
a_obj = anotherclass::proxy::create();
endfunction
endclass
41
42
Agenda: Day 1
DAY
1
OOP Inheritance Review
UVM Overview
Modeling Transactions
Creating Stimulus Sequences
43
Unit Objectives
After completing this unit, you should be able to:
n
Describe the process of reaching verification
goals
Describe the UVM testbench architecture
Describe the different components of a UVM
testbench
Bring different components together to create a
UVM environment
44
Origin of UVM
e
eRM
uRM
SV
OVM
UVM
AVM
SC
System
C
TLM 1.0
VMM
1.0
SV
OV
System
C
TLM 2.0
VMM
1.2
RVM
45
Verification Goal
n
Ensure full conformance with specification:
l
Must avoid false passes
Testbench
Simulation
result
Pass
RTL code
Good
Bad(bug)
False pass
results in shipping
a bad design
???
Tape out!
Fail
Debug
testbench
Debug
RTL code
How do we achieve this goal?
46
Coverage-Driven Verification
n
Focus on uncovered areas
Trade-off authoring time for run-time
Progress measured using functional coverage
metrics
Productivity
gain
Coverage-Driven
Methodology
% Testcases
Goal
Directed
Methodology
Self-checking
random environment
development time
Time
47
Phases of Verification
Start with fully random environment. Continue
with more and more focused guided tests
Preliminary
Verification
Broad-Spectrum
Verification
Corner-case
Verification
% Coverage
Goal
Difficult to reach
Corner-case
Verification
Time
Build verification
environment
48
Run More Tests, Write Less Code
n
Environment and component classes rarely change
l
l
l
Sends good transactions as fast as possible
Keeps existing tests from breaking
Leave "hooks" so test can inject new behavior
u
Test extends testbench classes
l
l
l
Virtual methods, factories, callbacks
Add constraints to reach corner cases
Override existing classes for new functionality
Inject errors, delays with callbacks
Run each test with hundreds of seeds
49
The Testbench Environment/Architecture
n
SystemVerilog Testbench Structure
Testcase
Testcase
Testcase
Testcase
Creates
random
transactions
Process
transactions
Collection of testcases
Coverage
Sequencer
Driver
Test
Sequencer
Self Check
Bus
Monitor
Bus
Monitor
Driver
Reacts to
transactions
Interface
DUT
RTL
50
UVM Encourages Encapsulation for Reuse
n
Structure should be architected for reuse
Test instantiates
the environment
and modifies the
environment on a
testcase by
testcase basis
Agents, coverage
and scoreboard
should be
encapsulated in
an environment
Sequencer, driver
and monitor
associated with an
interface should be
encapsulated as
an agent for that
interface
Top Level Harness
Test
Environment
Master Agent
Coverage
Sequencer
Driver
Slave Agent
Sequencer
Scoreboard
Bus
Monitor
Bus
Monitor
Driver
DUT
51
UVM Structure is Scalable
n
Agents are the building blocks across test/projects
Top Level Harness
Test
Environment
Scoreboard
Master Agent
Passive
A
g
e
n
t
Sequencer
Driver
Bus
Monitor
DUTA
Coverage
Scoreboard
Slave Agent
Slave Agent
Slave Agent
Slave Agent
Sequencer
Sequencer
Sequencer
Sequencer
Bus
Driver
Bus
MonitorDriver
Bus
Monitor Driver
Bus
Monitor Driver
Monitor
Bus
Monitor
DUTB
DUTB
DUTB
DUTB
52
Structural Support in UVM
n
Structural & Behavioral
l
uvm_component
u
uvm_test
uvm_env
u uvm_agent
u
uvm_sequencer
u uvm_driver
u uvm_monitor
u uvm_scoreboard
u
Test
Environment
Master Agent
Slave Agent
Coverage
Sequencer
Sequencer
Scoreboard
Driver
Bus
Monitor
Bus
Monitor
Driver
Communication
l
l
Top Level Harness
uvm_*_port
uvm_*_socket
DUT
Data
l
uvm_sequence_item
53
Component Phasing
n
The run phase task executes concurrently with the
scheduled run time phase tasks
Build Time
Run Time
Run-Time
Tasks
Cleanup
54
Hello World Example
n
n
UVM tests are derived from uvm_test class
Execution of test is done via global task run_test()
program automatic test;
Test
import uvm_pkg::*;
base class
class hello_world extends uvm_test;
DUT functional
verification
code resides in
one of the task
phases
`uvm_component_utils(hello_world)
function new(string name, uvm_component parent);
[Link](name, parent);
endfunction
virtual task run_phase(uvm_phase phase);
`uvm_info(TEST, Hello World!, UVM_MEDIUM);
endtask
endclass
Execute test
Create and
register test name
Message
initial
run_test();
endprogram
55
Compile and Simulate
n
n
Compile with ntb_opt uvm-1.0 switch
Specify test to run with +UVM_TESTNAME switch
[Link]
program automatic test;
import uvm_pkg::*;
class hello_world extends uvm_test;
test name
`uvm_component_utils(hello_world)
function new(string name, uvm_component parent);
[Link](name, parent);
endfunction
virtual task run_phase(uvm_phase phase);
`uvm_info(TEST, Hello World!, UVM_MEDIUM);
endtask
Compile with vcs: (using UVM in VCS installation)
endclass
vcs sverilog ntb_opts uvm-1.0 [Link]
initial
Simulate with:
run_test();
simv +UVM_TESTNAME=hello_world
endprogram
UVM_INFO @ 0: reporter [RNTST] Running test hello_world ...
UVM_INFO ./[Link](10) @ 0: uvm_test_top [TEST] Hello World!
56
Inner Workings of UVM Simulation
n
Macro registers the class in factory registry table
class hello_world extends uvm_test;
`uvm_component_utils(hello_world)
UVM package creates a global instance
of uvm_root class named uvm_top
Registry table
hello_world
simv
uvm_top
import uvm_pkg::*;
When run_test() executes, uvm_top
uvm_test_top
retrieves +UVM_TESTNAME from registry and creates a
child component called uvm_test_top
initial
n During
run_test();
execution,
parent component
simv +UVM_TESTNAME=hello_world
manages children components
phase execution
build
connect
end_of_elaboration
start_of_simulation
run*
extract
check
report
final
57
1
2
3
4
User Control of Reporting and Filtering
Print messages with UVM macros
Failure messages
are always
displayed
`uvm_fatal(CFGERR, Fatal message);
`uvm_error(RNDERR, Error message);
`uvm_warning(WARN, Warning message);
`uvm_info(NORMAL, Normal message, UVM_MEDIUM);
`uvm_info(TRACE, Tracing execution, UVM_HIGH);
`uvm_info(FULL, Debugging operation, UVM_FULL);
`uvm_info(DEBUG, Verbose message, UVM_DEBUG);
More verbose
Info messages need
to specify verbosity
Verbosity filter defaults to UVM_MEDIUM
l
User can modify run-time filter via +UVM_VERBOSITY switch
simv +UVM_VERBOSITY=UVM_DEBUG +UVM_TESTNAME=hello_world
58
Key Component Concepts: Parent-Child
n
Parent-child relationships
l
l
l
Phase execution order
l
Set up at component creation
Establishes component phasing execution order
Establishes component search path for component
configuration and factory replacement
Logical hierarchy Not OOP or composition hierarchy
Each component follows
the same sequence of
phase execution
Search path allow tests to:
l
l
build
connect
end_of_elaboration
start_of_simulation
run*
extract
check
report
final
Search and configure components
Search and replace components in environment
59
Key Component Concepts: Logical Hierarchy
class test_base extends uvm_test;
environment env;
`uvm_component_utils(test_base)
function new(string name, uvm_component parent);
function void build_phase(uvm_phase phase);
super.build_phase(phase);
env = environment::type_id::create(env, this);
Establish parentendfunction
endclass
class environment extends uvm_env; child
relationship at
component comp;
`uvm_component_utils(environment) creation
function new(string name, uvm_component parent);
function void build_phase(uvm_phase phase);
super.build_phase(phase);
comp = component::type_id::create("comp", this);
endfunction
Set
endclass
class component extends uvm_component;
Parent
`uvm_component_utils(component)
function new(string name, uvm_component parent);
[Link](name, parent);
Parent
endfunction
handle
virtual task component_task();
endclass
simv
uvm_top
run_test()
uvm_test_top
uvm_test_top
env
env
comp
comp
60
Key Component Concepts: Phase
n
Parent-child relationship dictates
phase execution order
l
uvm_top
run_test()
Functions are executed bottom-up
u
simv
Except for build phase which is
executed top-down
uvm_test_top
uvm_test_top
Tasks are forked into concurrent
executing threads
env
run_test()
uvm_test_top
env
comp
build
connect
end_of_elaboration
start_of_simulation
run
extract
check
report
final
build
connect
end_of_elaboration
start_of_simulation
run
extract
check
report
final
bld
cnt
eoe
sos
run
ext
chk
rpt
fnl
bld
cnt
eoe
sos
run
ext
chk
rpt
fnl
env
comp
comp
61
Key Component Concepts: Search & Replace
class test_new extends test_base; ...
`uvm_component_utils(test_new)
Simulate with:
function void build_phase(uvm_phase);
simv +UVM_TESTNAME=test_new
super.build_phase(phase);
set_inst_override("[Link]", "component", "new_comp");
endfunction
Use parent-child relationship
endclass
simv
to do search and replace for
components
class environment extends uvm_env;
...
function void build_phase(uvm_phase phase);
super.build_phase(phase);
comp = component::type_id::create("comp", this);
endfunction
create() used
endclass
to build
class new_comp extends component;
component
`uvm_component_utils(new_comp)
function new(string name, uvm_component parent);
virtual task component_task();
// modified component functionality
endtask
Modify
endclass
operation
uvm_top
run_test()
uvm_test_top
uvm_test_top
env
env
comp
comp
new_comp
4
3
2
1
62
Key UVM Elements (1/2)
n
TLM library classes
l
Classes for communication between components
Transaction class
l
Encapsulates stimulus data structure
class packet extends uvm_sequence_item;
Sequence class
l
Encapsulates transactions to be processed by driver
class packet_sequence extends uvm_sequence #(packet);
Sequencer class
l
Executes sequence and passes transactions to driver
typedef uvm_sequencer #(packet) packet_sequencer;
Driver class
l
Receives transaction from sequencer and drives DUT
class driver extends uvm_driver #(packet);
63
Key UVM Elements (2/2)
n
Agent class
l
Encapsulates sequencer, driver and monitor on a
per interface basis
class router_agent extends uvm_agent;
Environment class
l
l
Encapsulates all components of testbench
Connect components via TLM ports
class router_env extends uvm_env;
Test class
l
l
Encapsulates environment objects
Sets test-level configuration/modification
class test_base extends uvm_test;
64
Simple Example of Key UVM Elements
n
Test
l
Environment
l
uvm_sequencer
Data class
l
Test
Environment
Agent
uvm_agent
Sequencer
l
uvm_env
Agent
l
uvm_test
uvm_sequence
uvm_sequence_item
Sequencer
Sequence
default_sequence
Sequence_item
Driver
Driver (BFM)
l
uvm_driver
Communication (TLM)
For simplicity, monitor and other components are left off
65
Key UVM Testbench Elements: TLM
n
Communication between testbench components
l
l
l
Analysis ports for passive communication
l
l
l
Unidirectional or bidirectional communication
Blocking and non-blocking interfaces
Details in TLM Unit
put() and get() functionality
Monitors, Scoreboards, Functional Coverage
Always non-blocking, Broadcasting
write() functionality
Agent
TLM Base Classes
l
l
l
Sequencer
uvm_*_port/_imp/export
uvm_*_fifo_*
uvm_*_socket
Many UVM components
have built-in TLM ports
default_sequence
Driver
66
Key UVM Element: Transaction Class
n
Declare stimulus properties
l
Enable all properties for randomization with rand
Use macros to create support infrastructure
Sequence
packet
class packet extends uvm_sequence_item;
rand bit[3:0] sa, da;
rand bit[7:0] payload[$];
constraint valid {[Link] inside {[2:100]};}
`uvm_object_utils_begin(packet)
Macro creates support methods:
`uvm_field_int(sa, UVM_ALL_ON)
`uvm_field_int(da, UVM_ALL_ON) copy(), print() etc.
`uvm_field_queue_int(payload, UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = packet);
[Link](name);
endfunction
endclass
67
Key UVM Element: Sequence Class
n
Stimulus transactions are created inside a UVM
sequence extended from uvm_sequence class
Sequence must be typed for a specific sequence
item class
class packet_sequence extends uvm_sequence #(packet);
Registers
`uvm_object_utils(packet_sequence)
function new(string name = "packet_sequence"); sequence
[Link](name);
Sequence code
endfunction
packet_sequence
resides in body()
task body();
packet
if (starting_phase != null)
starting_phase.raise_objection(this);
repeat(10) begin
Randomize built-in transaction
`uvm_do(req);
object. Parent sequencer will output
end
transaction.
if (starting_phase != null)
starting_phase.drop_objection(this);
endtask
Use raise/drop objection
endclass
to stay in phase until
done
68
Key UVM Element: Sequencer Class
n
Use uvm_sequencer class
l
Contains a sequence descriptor ("default_sequence")
l
Parameterized to a chosen transaction class
Must be configured to reference a test sequence
Contains a built-in TLM port (seq_item_export)
l
Must be connected to a driver
typedef uvm_sequencer #(packet) packet_sequencer;
Must be typed for
a sequence item
class
Agent
packet_sequencer
default_sequence
Driver
69
Key UVM Element: Driver Class
n
Driver should extend from uvm_driver class
l
uvm_driver class has built-in sequence item handle
(req) and TLM port to communicate with the sequencer
Must be typed for
a sequence item
class
class driver extends uvm_driver #(packet);
`uvm_component_utils(driver)
function new(string name, uvm_component parent);
[Link](name, parent);
endfunction
task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
`uvm_info(DRVR, [Link](), UVM_MEDIUM);
seq_item_port.item_done();
end
endtask
Driver should implement
endclass
run phase to handle
sequences from all Run
Time task phases
Agent
packet_sequencer
default_sequence
driver
70
Key UVM Element: Agent Class
n
Encapsulated sequencer, driver and monitor as agent
l
Monitor is left off for simplicity (more on agent in later unit)
Extend from
class router_agent extends uvm_agent;
packet_sequencer seqr; driver drv;
uvm_agent
// utils macro and constructor not shown
function void build_phase(uvm_phase phase); super.build_phase(phase);
seqr = packet_sequencer::type_id::create("seqr", this);
drv = driver::type_id::create("drv", this);
endfunction
In build phase, use factory
create() method to construct
components
function void connect_phase(uvm_phase phase);
drv.seq_item_port.connect(seqr.seq_item_export);
endfunction
endclass
router_agent
packet_sequencer
default_sequence
driver
InTLM
connect
ports to
phase,
be covered
connect
next
built-in TLM ports
71
Key UVM Element: Environment Class
n
Encapsulate agent in environment class
l
l
Only agent for now. (Scoreboard and others in later units)
Configure the agent sequencers default_sequence
class router_env extends uvm_env;
Extend
router_agent agent;
// utils macro and constructor not shown
from uvm_env
In build phase,
create agent
object
function void build_phase(uvm_phase phase);
super.build_phase(phase);
agent = router_agent::type_id::create("agent", this);
uvm_config_db #(uvm_object_wrapper)::set(this, "*.seqr.main_phase",
"default_sequence", packet_sequence::get_type());
endfunction
endclass
Set agents sequencer
to execute a default
sequence
router_env
router_agent
packet_sequence
packet_sequencer
default_sequence
packet
driver
72
Key UVM Element: Test Class
n
Develop Tests In Two Steps
l
Create default test (unconstrained)
u
test_base extending from
the uvm_test base class
Base test
extends from
uvm_test
test_base
router_env
router_agent
packet_sequence
packet_sequencer
default_sequence
packet
class test_base extends uvm_test;
router_env env;
driver
`uvm_component_utils(test_base)
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
env = router_env::type_id::create(env, this);
endfunction
In build phase, create the environment
endclass
object
Then, develop targeted tests extending from test_base
u
Will be covered in each of the subsequent units
73
Test Program
n
Execute test in programs initial block
program automatic test;
...
initial begin
run_test();
end
endprogram
test_base
router_env
router_agent
run_test()
packet_sequence
uvm_top
uvm_test_top
packet_sequencer
default_sequence
packet
driver
Simulate with:
simv +UVM_TESTNAME=test_base
74
Key UVM Testbench Elements: UVM Report
n
Every UVM report has a severity, verbosity and
simulation handling specification
l
Each independently specified and controlled
Severity
Indicates importance
Examples: Fatal, Error, Warning, Info
l
Verbosity
Indicates filter level
Examples: None, Low, Medium, High, Full, Debug
l
Action
Controls simulator behavior
Examples: Exit, Count, Display, Log, Call Hook, No Action
l
75
Embed Report Messages
n
Create messages with macros:
`uvm_fatal(string ID, string MSG);
`uvm_error(string ID, string MSG);
`uvm_warning(string ID, string MSG);
`uvm_info(string ID, string MSG, verbosity);
Example:
function void build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info("Trace", $sformatf("%m"), UVM_HIGH)
if (![Link]()) begin
`uvm_fatal("CFG_ERROR", "Failed in Configuration randomization");
end
endfunction
UVM_FATAL ./[Link](14) @0.0ns: uvm_test_top[CFG_ERROR} Failed in
Severity
Time
File line no.
ID
Object name
MSG
76
Controlling Report Message Verbosity
n
Default Verbosity is UVM_MEDIUM
Set with run-time switch
simv +verbosity=UVM_HIGH
typedef enum {
UVM_NONE
= 0,
UVM_LOW
= 100,
UVM_MEDIUM = 200,
UVM_HIGH
= 300,
UVM_FULL
= 400,
UVM_DEBUG = 500
} uvm_verbosity;
Can be:
LOW, MEDIUM, HIGH, FULL, DEBUG,
UVM_LOW, UVM_MEDIUM, UVM_HIGH, UVM_FULL, UVM_DEBUG
Set verbosity for a component or hierarchy:
drv.set_report_verbosity_level(verbosity);
env.set_report_verbosity_level_hier(verbosity);
Exception:
`uvm_fatal, `uvm_error, and `uvm_warning
messages can not be filtered out via run-time switch
77
Default Simulation Handling
Severity
Default Action
UVM_FATAL
UVM_DISPLAY | UVM_EXIT
UVM_ERROR
UVM_DISPLAY | UVM_COUNT
UVM_WARNING
UVM_DISPLAY
UVM_INFO
UVM_DISPLAY
Action
Description
UVM_EXIT
Exit from simulation immediately
UVM_COUNT
Increment global error count. Set count for exiting
simulation, call set_report_max_quit_count()
UVM_DISPLAY
Display message on console
UVM_LOG
Captures message in a named file
UVM_CALL_HOOK
Calls callback method
UVM_NO_ACTION
Do nothing
78
Modify Report Message Action in Test
n
Actions can be modified by user
l
In start_of_simulation phase
set_report_severity_action(Severity, Action);
set_report_id_action(ID, Action);
set_report_severity_id_action(Severity, ID, Action);
n Priority:
set_report_severity_action()
(lowest)
set_report_id_action()
set_report_severity_id_action() (highest)
Example:
set_report_severity_action(UVM_FATAL, UVM_LOG | UVM_DISPLAY);
set_report_id_action("CFG_ERROR", UVM_NO_ACTION);
set_report_severity_id_action(UVM_ERROR, "CFG_ERROR", UVM_EXIT);
79
Command Line Control of Report Messages
n
Control verbosity of components at specific phases or times
l
id argument can be _ALL_ for all IDs or a specific id
u
Wildcard for id argument not supported
+uvm_set_verbosity=<comp>,<id>,<verbosity>,<phase>
+uvm_set_verbosity=<comp>,<id>,<verbosity>,time,<time>
+uvm_set_verbosity=uvm_test_top.env.agent1.*,_ALL_,UVM_FULL,time,800
n
Control report message action (like set_report_*_action)
l
Can be UVM_NO_ACTION or a | separated list of the other actions
+uvm_set_action=<comp>,<id>,<severity>,<action>
+uvm_set_action=uvm_test_top.env.*,_ALL_,UVM_ERROR,UVM_NO_ACTION
n
Control severity (like set_report_*_severity_override)
+uvm_set_severity=<comp>,<id>,<current severity>,<new severity>
+uvm_set_severity=uvm_test_top.*,BAD_CRC,UVM_ERROR,UVM_WARNING
80
Misc: Command Line Processor
n
User can query run-time arguments
class test_base extends uvm_test; // simplified code
uvm_cmdline_processor clp = uvm_cmdline_processor::get_inst();
function void build_phase(uvm_phase phase);
super.build_phase(phase);
// simplified code
if (clp.get_arg_value("+packet_item_count=", value))
uvm_config_db#(int)::set(this, "*.seqr.*", "item_count",
[Link]());
endfunction
function void start_of_simulation_phase(uvm_phase phase);
string tool, ver, args[$], m;
tool = clp.get_tool_name();
ver = clp.get_tool_version();
`uvm_info("TOOL_INFO",
$sformatf("Tool: %s, Version : %s", tool, ver), UVM_LOW);
clp.get_args(args);
foreach (args[i])
$sformat(m, {m, args[i], " "});
`uvm_info("ARGS", $sformatf("Sim cmd is:\n%s", m), UVM_LOW);
endfunction
endclass
81
Misc: Objection Run-Time Argument
n User can debug raising/dropping
+UVM_OBJECTION_TRACE
of objections with
Simulate with:
simv +UVM_TESTNAME=test_base +UVM_OBJECTION_TRACE
UVM_INFO @ 0.0ns: main [OBJTN_TRC] Object uvm_test_top.[Link].packet_sequence raised 1 objection(s): count=1
total=1
UVM_INFO @ 0.0ns: main [OBJTN_TRC] Object uvm_test_top.[Link] added 1 objection(s) to its total (raised from source
object ): count=0 total=1
UVM_INFO @ 0.0ns: main [OBJTN_TRC] Object uvm_test_top.[Link] added 1 objection(s) to its total (raised from source
object ): count=0 total=1
UVM_INFO @ 0.0ns: main [OBJTN_TRC] Object uvm_test_top.env added 1 objection(s) to its total (raised from source object ):
count=0 total=1
UVM_INFO @ 0.0ns: main [OBJTN_TRC] Object uvm_test_top added 1 objection(s) to its total (raised from source object
uvm_test_top.[Link].packet_sequence): count=0 total=1
UVM_INFO @ 0.0ns: main [OBJTN_TRC] Object uvm_top added 1 objection(s) to its total (raised from source object
uvm_test_top.[Link].packet_sequence): count=0 total=1
UVM_INFO @ 0.0ns: main [OBJTN_TRC] Object uvm_test_top.[Link].packet_sequence dropped 1 objection(s): count=0
total=0
UVM_INFO @ 0.0ns: main [OBJTN_TRC] Object uvm_test_top.[Link].packet_sequence all_dropped 1 objection(s):
count=0 total=0
UVM_INFO @ 0.0ns: main [OBJTN_TRC] Object uvm_test_top.[Link] subtracted 1 objection(s) from its total (dropped
from source object ): count=0 total=0
UVM_INFO @ 0.0ns: main [OBJTN_TRC] Object uvm_top subtracted 1 objection(s) from its total (dropped from source object
uvm_test_top.[Link].packet_sequence): count=0 total=0
UVM_INFO @ 0.0ns: main [OBJTN_TRC] Object uvm_top subtracted 1 objection(s) from its total (all_dropped from source object
82
uvm_test_top.[Link].packet_sequence): count=0 total=0
Unit Objectives Review
Having completed this unit, you should be able to:
n
Describe the process of reaching verification goals
Describe the UVM testbench architecture
Describe the different components of a UVM
testbench
Bring different components together to create a
UVM environment
83
Lab 1 Introduction
Implement transaction, components, and test
30 min
Implement
Transaction
Class
Implement
Sequence
Class
Implement
Component
Classes
Implement
Test
Compile
and
Simulate
84
Appendix
VCS Support for UVM
Store UVM Report Messages
in File
Calling UVM Messaging From
Modules
85
VCS Support for UVM
86
Compiling UVM with VCS 2011.03
n
Single compile flow
% vcs sverilog [Link] -ntb_opts uvm-1.0
%
%
%
%
%
UUM compile flow
Compile UVM library first
with no source files
vlogan sverilog work work1 -ntb_opts uvm-1.0
vlogan sverilog work work1 -ntb_opts uvm-1.0 file1.v
vlogan sverilog work work2 -ntb_opts uvm-1.0 file2.v
vhdlan work work3 [Link]
vcs top -ntb_opts uvm-1.0
When using the VPI-based backdoor access mechanism included in the UVM
library, the "+acc" and "+vpi" command-line options must also be used.
87
DVE UVM Macro Debugging
UVM Object Utils Macros
88
DVE UVM Transaction Level Debugging
n
Simple compile flow
% vcs sverilog -ntb_opts uvm lca +define+UVM_TR_RECORD
% simv +UVM_TR_RECORD +UVM_LOG_RECORD
Dumps UVM sequence items to VPD
Dumps UVM log messages to VPD
UUM compile flow
% vlogan -ntb_opts uvm lca +define+UVM_TR_RECORD
% vlogan -ntb_opts uvm [Link]
% vcs <top_module> $VCS_HOME/etc/uvm-1.0/dpi/uvm_dpi.cc
% simv +UVM_TR_RECORD +UVM_LOG_RECORD
89
UVM Template Generator (Coming Soon)
0) Physical interface declaration
1) Transaction descriptor
2) Driver, Physical-level, Full duplex
3) Driver, Functional-level, Full duplex
4) Generic Master Agent
5) Generic Slave Agent
6) Monitor, Physical-level, Half duplex
7) Monitor, Physical-level, Full duplex
16) Top Program/Module block
17) Sequence Library
18) Sequencers
19) Transaction descriptor testcase
20) Monitor Scoreboard Callbacks
21) Coverage Template
25) Monitor To coverage model Connector
26) Configuration descriptor
27) Hierarchical sequences (virtual)
8) Monitor, Functional-level, Half duplex
9) Monitor, Functional-level, Full duplex
10) RAL physical access BFM, single domain
11) RAL physical access BFM, multiplexed domains
12) Verification Environment (RAL or non-RAL)
13) Verification Environment with Agents (RAL or non-RAL)
14) Testcase
15) Agents
90
Store UVM Report Messages in File
91
Store Report Message in File
n
Message Action set to UVM_LOG causes the report
message to be stored in file
set_report_default_file(UVM_FILE);
set_report_severity_file(Severity, UVM_FILE)
set_report_id_file(ID, UVM_FILE);
set_report_severity_id_file(Severity, ID, UVM_FILE);
Example:
UVM_FILE log, err_log;
log
= $fopen("log", "w");
err_log = $fopen("[Link]", "w");
set_report_default_file(log);
set_report_severity_file(UVM_FATAL, err_log);
set_report_severity_action(UVM_FATAL, UVM_EXIT, UVM_LOG, UVM_DISPLAY);
set_report_id_file("Trace", UVM_LOG | UVM_DISPLAY)
Combine multiple actions with bitwise or
92
Calling UVM Messaging From Modules
93
Calling UVM Messaging From Modules (1/2)
n
The UVM messaging works well in the testbench,
but what about non-SystemVerilog RTL?
l
Create a global module to connect RTL and UVM
module GLOBAL;
import uvm_pkg::*;
//enumeration literals have to be separately imported
import uvm_pkg::UVM_HIGH; // And all the rest...
// Verilog-2001 compatible function
function reg uvm_info(input reg[100*8:1] ID,
input reg[1000*8:1] message,
input int verbosity);
`uvm_info(ID, message, verbosity);
uvm_info = 1;
endfunction
endmodule
//optional macros
`define G_UVM_HIGH
GLOBAL.UVM_HIGH
`define G_UVM_INFO(i,m,v) GLOBAL.uvm_info(i,m,v)
94
Calling UVM Messaging From Modules (2/2)
n
Call UVM messaging from RTL
l
Code does not require an SystemVerilog constructs
module dut(input reg reset_l, );
parameter DISPLAY_WIDTH = 1000;
reg [DISPLAY_WIDTH*8:1] message;
always @(negedge reset_l) begin
$sformat(message, %m: reset asserted at %t, $realtime);
`G_UVM_INFO(RESET, message, G_UVM_HIGH);
end
endmodule
95
96
Agenda: Day 1
DAY
1
OOP Inheritance Review
UVM Overview
Modeling Transactions
Creating Stimulus Sequences
97
Unit Objectives
After completing this unit, you should be able to:
n
Build data models by inheriting from
uvm_sequence_item
Use shorthand-hand macros to create
uvm_sequence_item methods
Configure test with modified sequence items
98
Transaction Flow
Stimulus
created
here
Accumulated
here
Tests
Sequencer
Master
Freed
here
Freed
here
Sequencer
Scoreboard
Monitor
Created
here
Monitor
Slave
DUT
99
Modeling Transactions
n
Derive from uvm_sequence_item base class
l
Properties should be public by default
l
Built-in support for stimulus creation, printing, comparing, etc.
Must be visible to constraints in other classes
Properties should be rand by default
l
Can be turned off with rand_mode
class packet extends uvm_sequence_item;
rand bit [47:0] sa, da;
rand bit [15:0] len;
rand bit [ 7:0] payload[$];
rand bit [31:0] fcs;
function new(string name = packet);
[Link](name);
[Link].rand_mode(0);
endfunction
endclass
100
Other Properties to be Considered (1/2)
n
Embed transaction descriptor
l
Component interprets transaction to execute
class cpu_data extends uvm_sequence_item;
typedef enum {READ, WRITE} kind_t;
rand int delay = 0;
rand kind_t kind;
rand bit [31:0] addr;
rand bit [31:0] data;
function new(string name="cpu_data");
[Link](name);
[Link].rand_mode(0);
endfunction class cpu_driver extend uvm_driver #(cpu_data);
endclass
task do(cpu_data tr);
repeat([Link]) @(router_vi.[Link]);
case ([Link]) begin
cpu_data::READ:
[Link] = [Link]([Link]);
cpu_data::WRITE:
[Link]([Link], [Link]);
endcase
endtask
endclass
101
Other Properties to be Considered (2/2)
n
Embed transaction status flags
l
Set by component for execution status
class cpu_data extends uvm_sequence_item;
typedef enum {IS_OK, ERROR} status_e;
rand status_e status = IS_OK;
...
function new(string name=cpu_data);
[Link](name);
...
[Link].rand_mode(0);
endfunction class cpu_driver extend uvm_driver #(cpu_data);
endclass
task do(cpu_data tr);
repeat([Link]) @([Link]);
case ([Link]) begin
...
endcase
if (error_condition_encountered)
[Link] = cpu_data::ERROR;
`uvm_info(DEBUG, [Link](), UVM_HIGH)
endtask
endclass
102
Transactions: Must-Obey Constraints
n
Define constraint block for the must-obey constraints
l
l
l
Never turned off
Never overridden
Name "class_name_valid"
Example:
l
Non-negative values for int properties
class packet extends uvm_sequence_item;
rand int len;
...
constraint packet_valid {
len > 0;
}
endclass
103
Transactions: Should-Obey Constraints
n
Define constraint block for should-obey constraints
l
l
Can be turned off to inject errors
One block per relationship set
u
Can be individually turned off or overloaded
Name "class_name_rule"
class packet extends uvm_sequence_item;
...
constraint packet_sa_local {
sa[41:40]
== 2'b0;
}
constraint packet_ieee {
len
in {46:1500};
[Link]() == len;
...
}
constraint packet_fcs {
...
fcs == 32'h0000_0000;
}
endclass
104
Transactions: Constraint Considerations
n
Cant accidentally violate valid constraints
l
Constraint solver will fail if the user constraints conflict
with valid constraints
Total solution
space
Illegal solution
Space
Valid solution
space
Test constraints
Derived
Test constraints
105
Transaction Class Methods
n
How to manipulate transactions?
l
l
Print, copy, compare, record, pack
UVM has standard methods for these actions
n Use macros to create commonly
`uvm_object_utils_begin(cname)
needed methods
`uvm_field_*(ARG, FLAG)
`uvm_object_utils_end
class packet extends uvm_sequence_item;
rand bit [47:0] sa, da;
rand bit [ 7:0] payload[$];
packet
next;
`uvm_object_utils_begin(packet)
`uvm_field_int(sa, UVM_ALL_ON | UVM_NOCOPY)
`uvm_field_int(da, UVM_ALL_ON)
`uvm_field_queue_int(payload, UVM_ALL_ON)
`uvm_field_object(next, UVM_ALL_ON)
`uvm_object_utils_end
endclass
106
`uvm_field_* Macros
n
`uvm_field_* macros embed ARG properties in
methods specified by FLAG
Scalar and array properties are supported
uvm_field_int(ARG, FLAG)
uvm_field_real(ARG, FLAG)
uvm_field_event(ARG, FLAG)
uvm_field_object(ARG, FLAG)
uvm_field_string(ARG, FLAG)
uvm_field_enum(T, ARG, FLAG)
uvm_field_sarray_*(ARG, FLAG)
uvm_field_array_*(ARG, FLAG)
uvm_field_queue_*(ARG, FLAG)
uvm_field_aa_*_*(ARG, FLAG)
//
//
//
//
//
T enum data type
fixed size array:
dynamic array:
queue:
associative array:
_type
_type
_type
_type_index
107
Methods Specified by FLAG
n
FLAG is a collection of ON/OFF bits associated with
the base class methods
//A=ABSTRACT Y=PHYSICAL, F=REFERENCE, S=SHALLOW, D=DEEP
//K=PACK, R=RECORD, P=PRINT, M=COMPARE, C=COPY
//------------------------- AYFSD K R P M C
parameter UVM_DEFAULT
= 'b000010101010101;
parameter UVM_ALL_ON
= 'b000000101010101;
//Values are or'ed into a 32 bit value
parameter UVM_COPY
= (1<<0); // copy(...)
parameter UVM_NOCOPY
= (1<<1);
parameter UVM_COMPARE
= (1<<2); // compare(...)
parameter UVM_NOCOMPARE = (1<<3);
parameter UVM_PRINT
= (1<<4); // sprint(...)
parameter UVM_NOPRINT
= (1<<5);
parameter UVM_RECORD
= (1<<6); // record(...)
parameter UVM_NORECORD = (1<<7);
parameter UVM_PACK
= (1<<8); // pack(...)
parameter UVM_NOPACK
= (1<<9);
// Disable printing for a hidden field
`uvm_field_int(hidden_field, UVM_ALL_ON | UVM_NOPRINT)
108
Print Radix Specified by FLAG
n
Additional FLAG can be used to set radix for print
method
Radix for printing and recording can be specified by OR'ing one of the following constants
in the ~FLAG~ argument
UVM_BIN
UVM_DEC
UVM_UNSIGNED
UVM_OCT
UVM_HEX
UVM_STRING
UVM_TIME
UVM_REAL
Print/record
Print/record
Print/record
Print/record
Print/record
Print/record
Print/record
Print/record
field in binary (base-2)
field in decimal (base-10)
field in unsigned decimal (base-10)
the field in octal (base-8)
the field in hexadecimal (base-16)
the field in string format
the field in time format
the field in floating number format
// printing in decimal
`uvm_field_int(field, UVM_ALL_ON | UVM_DEC)
109
Transaction Methods
n
Default base class method
virtual function uvm_object clone();
Methods created by macros
For debugging
virtual function void print(uvm_printer printer = null)
virtual function string sprint(uvm_printer printer = null)
For making copies
virtual function void copy(uvm_object rhs);
Used by checker
virtual function bit
compare(uvm_object rhs,
uvm_comparer comparer = null);
virtual function int
pack(ref bit bitstream[],
input uvm_packer packer = null);
unpack(ref bit bitstream[],
input uvm_packer packer = null);
Used by transactors
virtual function int
For
recording/replaying
transactions
virtual function void record(uvm_recorder recorder = null);
110
Method Descriptions
methods
function
clone
The clone method creates and returns an exact copy of this object.
Calls create followed by copy
copy
Returns a deep copy of this object
print
Deep-prints this objects properties in a format and manner governed
by the given printer argument
sprint
Same as print, but returns a string
compare
Compare method deep compares this data object with the object
provided in the rhs
pack/unpack
Bitwise-concatenate objects properties into an array of bits, bytes, or
ints.
record
Deep-records this objects properties according to an optional
recorder policy
111
Customization of Methods
n
Methods can be customized via do_* methods
virtual function void do_print(uvm_printer printer = null)
virtual function void do_copy(uvm_object rhs);
virtual function bit
do_compare(uvm_object rhs,
uvm_comparer comparer = null);
virtual function int
do_pack(ref bit bitstream[],
input uvm_packer packer = null);
virtual function int
do_unpack(ref bit bitstream[],
input uvm_packer packer = null);
virtual function void do_record(uvm_recorder recorder = null);
112
Using Transaction Methods
name
packet pkt0, pkt1, pkt2;
string
bit bit_stream[];
pkt0 = packet::type_id::create(pkt0);
pkt1 = packet::type_id::create(pkt1);
[Link] = 10;
[Link]();
// display content of object on stdio
[Link](pkt1);
// copy content of pkt1 into memory of pkt0
// name string is not copied
$cast(pkt2, [Link]());
// make pkt2 an exact duplication of pkt1
// name string is copied
if() begin // compare the contents of pkt0 against pkt2
`uvm_fatal(MISMATCH, {\n, [Link](), [Link]()});
end
// sprint() returns string for logging
[Link](bit_stream);
// pack content of pkt0 into bit_stream array
[Link](bit_stream);
// unpack bit_stream array into pkt2 object
113
Modify Constraint in Transactions by Type
class packet extends uvm_sequence_item;
rand bit[3:0] sa, da;
rand bit[7:0] payload[];
constraint valid {[Link] inside {[2:10]};}
...
endclass
class packet_sa_3 extends packet;
constraint sa_3 {sa == 3;}
`uvm_object_utils(packet_sa_3)
function new(string name = "packet_sa_3");
[Link](name);
endfunction
endclass
class test_sa_3_type extends test_base;
The most common
transaction
modification is
constraint
`uvm_component_utils(test_sa_3_type)
function new(string name, uvm_component parent);
[Link](name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
set_type_override("packet", "packet_sa_3");
endfunction
All packet instances are now
endclass
packet_sa_3
114
Transaction Replacement Results
Simulate with:
simv +UVM_TESTNAME=test_sa_3_type
UVM_INFO @ 0: uvm_test_top.[Link] [Normal] Item in Driver
req: (packet_sa_3@95) {
sa: 'h3
da: 'h7
#### Factory Configuration (*)
Type Overrides:
Requested Type
-------------packet
Override Type
-------------------------------packet_sa_3
function void final_phase(uvm_phase phase);
[Link]();
endfunction
115
Modify Constraint by Instance
class test_sa_3_inst extends test_base;
// utils and constructor not shown
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
set_inst_override("*.seqr.*", "packet", "packet_sa_3");
endfunction
Only packet instances in matching sequencers are
endclass
now
packet_sa_3
Simulate with:
simv +UVM_TESTNAME=test_sa_3_inst
UVM_INFO @ 0: uvm_test_top.[Link] [Normal] Item in Driver
req: (packet_sa_3@95) {
sa: 'h3
da: 'h7
Instance Overrides:
Requested Type Override Path
Override Type
-------------- ----------------------- ------------packet
uvm_test_top.*.seqr.*
packet_sa_3
116
Data Model Reuse: Class Hierarchy
Company
best practices
uvm_sequence_item
Generic
bu_data
Company-specific
usb_packet
Protocol-specific
dut_usb_packet
Environment-specific
test_usb_packet
Test-specific
OOP
Reuse
across
projects
Reuse across tests
117
Unit Objectives Review
Having completed this unit, you should be able to:
n
Build data models by inheriting from
uvm_sequence_item
Use shorthand-hand macros to create
uvm_sequence_item methods
Configure test with modified sequence items
118
Lab 2 Introduction
Implement configurable sequence
15 min
Create class
with modified
Constraint
Use new class
in Test
Compile
and
Simulate
119
Appendix
uvm_object_utils Macro
120
uvm_object_utils Macros
`uvm_object_utils[_begin](cname) Macro creates a
proxy class called
n Implements the following:
type_id
typedef
static
static
virtual
virtual
uvm_object_registry #(cname, cname) type_id;
const string type_name = cname;
function type_id get_type();
function uvm_object_wrapper get_object_type();
function string get_type_name();
class uvm_object_registry #(type T=uvm_object, string Tname="<unknown>) extends uvm_object_wrapper;
typedef uvm_object_registry #(T,Tname) this_type;
const static string type_name = Tname;
Proxy class (type_id) is an service
local static this_type me = get();
static function this_type get();
agent that creates objects of the
if (me == null) begin
class it represents
uvm_factory f = uvm_factory::get();
me = new;
A proxy class object is registered
[Link](me);
end
in uvm_factory at beginning of
return me;
simulation
endfunction
Creation of object
is done via proxy
class (type_id)
methods
static function T create(string name="", uvm_component parent=null, string contxt="");
static function void set_type_override(uvm_object_wrapper override_type, bit replace=1);
static function void set_inst_override(uvm_object_wrapper override_type, string inst_path, uvm_component
parent=null);
virtual function string get_type_name();
virtual function uvm_object create_object(string name="");
121
uvm_factory Class Summary (1/2)
class uvm_factory;
static local uvm_factory m_inst;
Factory registry table
protected uvm_object_wrapper m_type_names[string];
protected bit
m_types[uvm_object_wrapper];
protected bit
m_lookup_strs[string];
protected uvm_factory_override m_type_overrides[$];
protected uvm_factory_queue_class m_inst_override_queues[uvm_object_wrapper];
protected uvm_factory_queue_class m_inst_override_name_queues[string];
protected uvm_factory_override m_wildcard_inst_overrides[$];
local uvm_factory_override m_override_info[$];
function new ();
static function uvm_factory get(); if (m_inst == null) m_inst = new(); return m_inst;
endfunction
function void register (uvm_object_wrapper obj);
m_type_names[obj.get_type_name()] = obj;
m_types[obj] = 1;
if(m_inst_override_name_queues.exists(obj.get_type_name())) begin
m_inst_override_queues[obj] = new;
m_inst_override_queues[obj].queue =
m_inst_override_name_queues[obj.get_type_name()].queue;
m_inst_override_name_queues.delete(obj.get_type_name());
end
if(m_wildcard_inst_overrides.size()) begin
if(! m_inst_override_queues.exists(obj)) m_inst_override_queues[obj] = new;
foreach (m_wildcard_inst_overrides[i]) begin
if(uvm_is_match(obj.get_type_name(), m_wildcard_inst_overrides[i].orig_type_name))
m_inst_override_queues[obj].queue.push_back(m_wildcard_inst_overrides[i]);
end end
122
uvm_factory Class Summary (2/2)
function void set_inst_override_by_type (uvm_object_wrapper original_type, override_type, string
full_inst_path);
function void set_inst_override_by_name(string original_type_name, override_type_name, full_inst_path);
function void set_type_override_by_type (uvm_object_wrapper original_type, override_type, bit replace=1);
function void set_type_override_by_name(string original_type_name, override_type_name, bit replace=1);
function uvm_object create_object_by_type(uvm_object_wrapper requested_type, string parent_inst_path=",
name="");
function uvm_component create_component_by_type (uvm_object_wrapper requested_type,
string parent_inst_path=", string name, uvm_component parent);
function uvm_object create_object_by_name(string requested_type_name, parent_inst_path=", name="");
function uvm_component create_component_by_name (string requested_type_name,
parent_inst_path=", name, uvm_component parent);
function void debug_create_by_type(uvm_object_wrapper requested_type, string parent_inst_path=",
name="");
function void debug_create_by_name (string requested_type_name, string parent_inst_path=", string
name="");
function uvm_object_wrapper find_override_by_type (uvm_object_wrapper requested_type, string
full_inst_path);
function uvm_object_wrapper find_override_by_name (string requested_type_name, string full_inst_path);
function uvm_object_wrapper find_by_name (string type_name);
function void print (int all_types=1);
protected function void m_debug_create(string requested_type_name, uvm_object_wrapper requested_type,
string parent_inst_path, string name);
protected function void m_debug_display(string requested_type_name, uvm_object_wrapper result, string
full_inst_path);
local static bit m_debug_pass;
123
124
Agenda: Day 1
DAY
1
OOP Inheritance Review
UVM Overview
Modeling Transactions
Creating Stimulus Sequences
125
Unit Objectives
After completing this unit, you should be able to:
n
Create sequences using base classes
Create complex sequences
Configure sequences
Setting sequences to execute at different
phases
126
Typical Sequence Execution Protocol
n
Sequencer and driver are
synchronized via TLM port
Test
Environment
Sequencer
Sequencer
Sequencer randomizes
sequence
(referenced by
default_sequence)
Sequencer executes
sequences
start() method
default_sequence
Sequence
Sequence_item
Driver
driver
Sequence
start() executes pre_body()
start() executes body()
body() generates sequence
item
(Subject of this unit)
start() executes
post_body()
Driver requests for
sequence item
Driver waits for sequence
item
Driver processes sequence
item
Driver flags sequence item
done
127
Mapping Protocol to Code (1/2)
Sequence
driver
start() executes pre_body()
start() executes body()
body() generates sequence
item
(Subject of this unit)
start() executes
post_body()
Driver requests for
sequence item
Driver waits for sequence
item
Driver processes
sequence item
Driver flags sequence item
done
class driver extends uvm_driver #(packet);
// utils and constructor not shown
virtual task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
`uvm_info(DRVR, [Link](), UVM_MEDIUM);
seq_item_port.item_done();
end
endtask
endclass
128
Mapping Protocol to Code (2/2)
class user_sequence extends uvm_sequence #(packet);
virtual task pre_body();
if (starting_phase != null)
starting_phase.raise_objection(this);
Driver wait for sequence
endtask
item
Sequencer randomizes
virtual task body();
sequence
Driver process sequence
`uvm_do(req);
(referencedendtask
by
item
default_sequence)
virtual task post_body();
Driver flags sequence item
Sequencer executes
if (starting_phase != null)
done
sequences starting_phase.drop_objection(this);
start() method
endtask
Sequence
endclass
Details in next few slides
start() executes pre_body()
start() executes body()
body() generate sequence
item
(Subject of this unit)
start() executes
post_body()
129
Sequence Class Requirements
n
n
User sequence extends from uvm_sequence class
Sequence code resides in body() method
l
Use uvm_do macro to create, randomize and pass
sequence item to driver
Sequences need to raise and drop phase objection
to allow sequences to span execution over time
class user_sequence extends uvm_sequence #(packet);
// macro and constructor not shown
virtual task body();
if (starting_phase != null)
starting_phase.raise_objection(this);
`uvm_do(req);
if (starting_phase != null)
starting_phase.drop_objection(this);
endtask
endclass
130
User Sequence Class Implementation
Simplify sequence implementation:
n Create base sequence to raise and drop objections
n Create user sequence extending from base sequence
class base_sequence extends uvm_sequence #(packet);
// macro and constructor not shown
virtual task pre_body();
if (starting_phase != null) starting_phase.raise_objection(this);
endtask
virtual task post_body();
if (starting_phase != null) starting_phase.drop_objection(this);
endtask
endclass
class user_sequence extends base_sequence;
// macro and constructor not shown
virtual task body();
`uvm_do(req);
// if constraint is required: `uvm_do_with(req, {sa == 3;});
endtask
endclass
131
User Can Manually Create and Send Item
n
`uvm_do* macro effectively implements the
following:
// Simplified code not complete code
`define uvm_do(UVM_SEQUENCE_ITEM) \
`uvm_create(UVM_SEQUENCE_ITEM) \
start_item(UVM_SEQUENCE_ITEM); \
UVM_SEQUENCE_ITEM.randomize(); \
finish_item(UVM_SEQUENCE_ITEM);
taskmanually
body();
n virtual
User can
//
//
execute the embedded methods:
Instead of `uvm_do_with(req, {sa == 3;})
User can populate own item:
`uvm_create(req); // constructs an item and sets item ids and link to parent
sequencer
start_item(req); // wait for parent sequencer to get request from driver
[Link] = 3;
// populate item with user value
...
finish_item(req); // use parent sequencer to pass item to driver and wait for
done
endtask
132
User Can Implement Scenario Sequence
class array_sequence extends base_sequence;
Use array of rand
// macro not shown
transactions to
rand packet arr[10];
constraint array_constraint {
create scenario
foreach(arr[i]) {
(i > 0) -> arr[i].sa == arr[i-1].sa + 1;
}
}
function new(string name=packet_sequence); [Link](name);
foreach(arr[i])
arr[i] = packet::type_id::create($sformatf("arr[%0d]", i));
endfunction
virtual task body();
foreach (arr[i]) begin
`uvm_create(req); // constructs an item and sets item ids and link to parent
sequencer
[Link](arr[i]); // copy scenario object content into req
start_item(req); // wait for access to parent sequencer
finish_item(req); // use parent sequencer to pass item to driver and wait for
done
end
endtask
endclass
133
Nested Sequences
n
Sequences can be nested
class noise_sequence extends base_sequence; // other code
virtual task body();
`uvm_info(get_name(), $sformatf(%m), UVM_HIGH);
class burst_sequence extends base_sequence; // other code
...
virtual task body();
endtask
`uvm_info(get_name(), $sformatf(%m), UVM_HIGH);
class
congested_sequence extends base_sequence; // other code
endclass
...
virtual task body();
endtask
`uvm_info(get_name(), $sformatf(%m), UVM_HIGH);
class nested_sequence extends base_sequence;
endclass
...
// utils macro and constructor not shown
endtask
noise_sequence
noise;
endclass
burst_sequence
burst;
congested_sequence congestion;
virtual task body();
`uvm_do(noise);
`uvm_do(burst);
`uvm_do(congestion);
endtask
endclass
134
Executing User Sequences in Test
n
Default test (test_base) executes default sequence
specified by embedded environment
class router_env extends uvm_env; // other code not shown
function void build_phase();
// simplified code
uvm_config_db #(uvm_object_wrapper)::set(this, "*.seqr.main_phase",
"default_sequence", packet_sequence::get_type());
class test_base extends uvm_test;
endfunction
router_env env;
endclass
// other code not shown
endclass
Test writer can override this in targeted tests
class test_nested extends test_base; // other code not shown
function void build_phase();
// simplified code
uvm_config_db#(uvm_object_wrapper)::set(this, "env.*.seqr.main_phase",
"default_sequence", nested_sequence::get_type());
endfunction
endclass
135
Sequence Can Be Configured (Local)
n
Reference configuration field through parent sequencer
class packet_sequence extends base_sequence;
int item_count = 10; // utils macro and constructor not shown
task body();
Parent
sequencer
Tag to get
value
uvm_config_db#(int)::get(m_sequencer,"*","item_count",item_count);
repeat(item_count) begin
`uvm_do(req)
Sequence instance
Variable to store
end
name
value
endtask
n Set in test
endclass
unchanged if not
set
class test_20_items extends test_base;
// utils and constructor not shown
function void build_phase(uvm_phase phase); Tag to set
super.build_phase(phase);
value
uvm_config_db#(int)::set(this, "*.seqr.*", "item_count", 20);
endfunction
Context of
Instance name in
Valu
endclass
search
context
136
Sequence Can Be Configured (Global)
n
Use resource database to configure sequence
class packet_sequence extends base_sequence;
int item_count = 1; // utils macro and constructor not shown
Scope where resource
task body();
reside
uvm_resource_db#(int)::read_by_name("SEQ_CNTRL",
"item_count", item_count);
repeat(item_count)begin
`uvm_do(req);
Field tag within resource
Variable to store
end
pool
value
endtask
endclass
unchanged if not
Set in test
set
class test_10_items extends test_base;
//utils and constructor not shown
function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_resource_db#(int)::set("SEQ_CNTRL", "item_count", 10);
endfunction
Scope where resource
Field
Valu
endclass
reside
137
Set Sequence to Execute at a Phase
n
Sequences be targeted for a chosen phase
l
Typically done at the testcase level
class simple_seq_RST extends uvm_sequence #();
class simple_seq_CFG extends uvm_sequence #();
class simple_seq_MAIN extends uvm_sequence #();
class simple_seq_SHUT extends uvm_sequence
#();
class phase_test
extends test_base;
typedef uvm_config_db #(uvm_object_wrapper) seq_phase;
// utils macro and constructor not shown
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
seq_phase::set(this, "[Link].reset_phase",
"default_sequence", simple_seq_RST::get_type());
seq_phase::set(this, "[Link].configure_phase",
"default_sequence", simple_seq_CFG::get_type());
seq_phase::set(this, "[Link].main_phase",
"default_sequence", simple_seq_MAIN::get_type());
seq_phase::set(this, "[Link].shutdown_phase",
"default_sequence", simple_seq_SHUT::get_type());
endfunction
endclass
138
Alternative Way to Execute Sequence
n
Execute sequence via sequences start() method:
class router_env extends uvm_env; // other code not shown
function void build_phase();
// simplified code
uvm_config_db #(uvm_object_wrapper)::set(this, "*.seqr.main_phase",
"default_sequence", packet_sequence::get_type());
endfunction
endclass
class test_explicit_sequence extends test_base;
// macro and constructor not shown
function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db#(uvm_object_wrapper)::set(this, "*.seqr.main_phase",
"default_sequence", base_sequence::get_type());
endfunction
task main_phase(uvm_phase phase);
nested_sequence seq = new();
Default sequence in sequencer
[Link]([Link]);
needs to be turned off. In UVM 1.0,
endtask
endclass
the only way to do that is to execute a
noop sequence.
139
Unit Objectives Review
Having completed this unit, you should be able to:
n
Create sequences using base classes
Create complex sequences
Configure sequences
Setting sequences to execute at different phases
140
Lab 3 Introduction
Implement configurable sequence
30 min
Create
configurable
sequence
Implement
Test
Compile
and
Simulate
141
Appendix
Sequencer-Driver
Communication
Sequencer-Driver Response
Port
142
Sequencer-Driver Communication
143
Sequencer-Driver Communication Detailed
n
Pseudo code illustration:
Sequencer
my_seq
`uvm_do(tr);
get_next_item(req)
send(req)
item_done();
task body();
repeat (10) begin
`uvm_do(req);
end
define uvm_do(req)
endtask
`uvm_create(req); task start_item(req);
start_item(req);
seqr.wait_for_grant();
[Link]();
seqr.begin_tr(req);
finish_item(req); endtask
Driver
class driver
task run_phase();
task finish_item(req);
forever begin
seqr.send_request(req);
seq_item_port.get_next_item(req);
seqr.wait_for_item_done();
send(req);
seqr.end_tr(req);
seq_item_port.item_done();
endtask
end
endtask
endclass
Caution: Pseudo code, not actual code
7
6
5
4
3
2
1
144
Another View of Sequencer-Driver Interaction
n
Pseudo code illustration:
task xxx_phase();
start_default_sequence();
endtask task start_default_sequence();
uvm_sequence seq = default_sequence;
[Link]()
[Link](this);
endtask task start (uvm_sequencer_base seqr);
pre_body();
task body();
body();
`uvm_create(req);
post_body();
Sequencer
seqr.wait_for_grant();
endtask
xxx_phase()
seqr.begin_tr(req);
get_next_item()
[Link]();
task get_next_item();
seqr.send_request(req);
select_sequence();
seqr.wait_for_item_done();
endtask
seqr.end_tr(req);
endtask
port.get_next_item(req)
send(req)
item_done();
Driver
Caution: Pseudo code, not actual code
145
Sequencer-Driver Response Port
146
Sequencer-Driver Response Port (1/2)
n
Driver can send response back to sequence
Retrieve
response
task body();
repeat (10) begin
`uvm_do(req);
get_response(rsp);
// process response
end
endtask
[Link]
Sequencer
my_seq
`uvm_do(tr);
get_response(rsp)
Optional
response
get_next_item(req)
class driver extends uvm_driver #(packet); send(req)
...
task run_phase(uvm_phase phase);
item_done(rsp);
forever begin
Driver
seq_item_port.get_next_item(req);
send(req);
Create and
rsp = packet::type_id::create(rsp);
rsp.set_id_info(req);
set response
// set rsp response
id
seq_item_port.item_done(rsp);
(required!)
end
endtask
Set response
endclass
147
Sequencer-Driver Response Port (2/2)
n
Alternative if the response timing is not immediate
l
E.g. out of order processing
Retrieve
response
task body();
repeat (10) begin
`uvm_do(req);
// create thread to wait for response
get_response(rsp);
// process response
end
class driver extends uvm_driver #(packet);
endtask
task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
send(req);
rsp = packet::type_id::create(rsp);
rsp.set_id_info(req);
seq_item_port.item_done();
// other activities
seq_item_port.put_response(rsp);
end
endtask
Set response
endclass
148
Agenda: Day 2
DAY
2
Component Configuration & Factory
TLM Communication
Scoreboard & Coverage
UVM Callback
149
Unit Objectives
After completing this unit, you should be able to:
n
Describe component logical hierarchy
Use logical hierarchy to get/set component
configuration fields
Use factory to create test replaceable
transaction and components
150
UVM Component Base Class Structure
n
Behavioral base class is uvm_component
l
l
Has logical parent-child relationship
Provides mechanism for phasing control & configuration
uvm_object
uvm_report_object
uvm_component
uvm_test
uvm_env
uvm_agent
is_active
req, rsp
uvm_sequencer_base
uvm_monitor
uvm_scoreboard
build
connect
end_of_elaboration
start_of_simulation
run*
extract
check
report
final
uvm_sequencer_param_base
uvm_sequencer
req, rsp
uvm_driver
151
Component Parent-Child Relationships
n
Logical relationship is established at creation of
component object
components
only
uvm_component; //
class child extends
utils macro
function new(string name, uvm_component parent);
[Link](name, parent);
endfunction
Pass parent in via
endclass
constructor
class BFM extends uvm_component; // utils macro
child child1, child2;
function new(string name, uvm_component parent);
[Link](name, parent);
endfunction
function void build_phase(); super.build_phase();
child1 = child::type_id::create("child1", this);
child2 = child::type_id::create("child2", this);
endfunction
endclass
Establish logical
...
hierarchy
BFM blk = BFM::type_id::create("blk", null);
blk
child1
child2
152
Display & Querying
n
Rich set of methods for query & display
Display all
members
Get logical
name
Get hierarchical
name
Find one
component
via logical
name
Find all
matching
components
[Link]();
string str = obj.get_name();
string str = obj.get_full_name();
Logical name
uvm_component obj;
obj = uvm_top.find(*.vip"));
uvm_component objs[$];
uvm_top.find_all(*.drv_?, objs);
foreach (objs[i]) begin
objs[i].print();
end
Can use wildcard
* match anything
? match one
character
153
Query Hierarchy Relationship
n
Easy to get handle to object parent/children
Get handle to
parent
Finding
object via
logical
name
Determine
number of
children
Iterate through
children
uvm_component obj;
obj = [Link].get_parent();
Logical name
uvm_component obj;
obj = vip1.get_child("bfm");
int num_ch = vip.get_num_children();
string name;
uvm_component child;
if (vip.get_first_child(name)) do begin
child = vip.get_child(name);
[Link]();
end while (vip.get_next_child(name));
154
Use Logical Hierarchy in Configuration
n
Mechanism for configuring object properties
Object context in which
the target instance name
Tag to get
resides
value
uvm_config_db#(type)::get(context,inst_name,field,var)
Hierarchical instance
name in context
Object context in which
the target instance name
reside
variable to store
value
unchanged if not
set
Tag to set
value
uvm_config_db#(type)::set(context,inst_name,field,valu
e)
Hierarchical instance
Value to
name in context
set
155
Configuration Example: Non-Object
n
Non-object field configuration
class driver extends uvm_driver #(packet);
Configuration fields
// constructor not shown
should be listed in
int port_id = -1; // user configurable
`uvm_component_utils_begin(driver)
component utils
`uvm_field_int(port_id, UVM_DEFAULT)
macro
`uvm_component_utils_end
function void build_phase();
If super.build_phase() is
super.build_phase(phase);
called, uvm_config_db::get()
uvm_config_db::set()
endfunction
not needed
virtual task run_phase();
// uvm_config_db #(int)::get(this, "", "port_id", port_id);
if (port_id == -1) ...;
else ...;
Set port_id to 10.
... class router_env extends uvm_env;
Can also be done in test
endtask // utils macro and constructor not shown
endclass virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db #(int)::set(this, "*.drv", "port_id", 10);
endfunction
endclass
156
Configuration Example: Object
n
Object field configuration
class driver extends uvm_driver #(packet);
// constructor not shown
packet tr; // user configurable
`uvm_component_utils_begin(driver)
`uvm_field_object(tr, UVM_DEFAULT)
`uvm_component_utils_end
virtual task run_phase(); ...
if (uvm_config_db #(packet)::get(this, "", "tr", tr)) begin
process(tr);
end else begin
uvm_config_db::get() required
process(req);
end
...
class driver_with_object_test extends test_base;
endtask
// utils and constructor not shown
endclassvirtual function void build_phase(uvm_phase phase);
packet tr = new(tr);
super.build_phase(phase);
[Link]() with { sa == 3; da == 7;};
uvm_config_db #(packet)::set(this, "*.drv", "tr", tr);
endfunction
endclass
157
Other Examples: Physical Interface
n
For physical layer connection, dont pass virtual
interface as constructor argument
l
Not supported by proxy class (type_id)
create() method
class driver extends uvm_driver#(packet);
virtual router_io.driver sigs;
...
function new(..., virtual router_io sigs);
[Link] = sigs;
...
endfunction
endclass
Generator
Agent
Driver
Physical
device driver
Use set/get methods in uvm_config_db
158
Configuring Components DUT Interface
n
In component, use uvm_config_db#(intf)::get()
in build_phase to retrieve DUT signal
class driver extends ; // simplified code
virtual router_io sigs;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(virtual router_io)::get(this, "",
"router_io", sigs))
`uvm_fatal("CFGERR", "Driver DUT interface not set");
endfunction
endclass
In test, use uvm_config_db#(intf)::set() in
build_phase to set DUT signal
class test_base extends ; // simplified code
function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db#(virtual router_io)::set(this, "env.*",
"router_io", router_test_top.sigs);
endfunction
endclass
159
One More Example: Reset Sequence
n
Create a sequence to reset DUT
class reset_sequence extends uvm_sequence; // simplified code
virtual router_io sigs;
task body();
if (!uvm_config_db#(virtual router_io)::get(m_sequencer, "*",
"router_io", sigs)) begin
`uvm_fatal("CFGERR", "DUT reset interface not set");
end else begin ... Reset Code ... end
endtask
endclass
Use uvm_config_db#()::set() to execute sequence
in reset_phase
class router_env extends uvm_env; // simplified code
function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db#(uvm_object_wrapper)::set(this, "seqr.reset_phase",
"default_sequence", reset_sequence::type_id::get());
endfunction
endclass
160
Global UVM Resource
n
n
uvm_config_db sets objects local configurations
For global configuration, use UVM resource
Scope where resource
reside
Content of
resource
uvm_resource_db#(d_type)::set(scope, key, value, accessor);
Name of
resource
Object making
call
n Retrieval of the resources can be done in
ways
(fortwo
debugging)
l Read by name
l Read by type
Variable of data type
Data type
uvm_resource_db#(d_type)::read_by_name(scope,key,type_var,accessor);
uvm_resource_db#(d_type)::read_by_type(scope, type_field, accessor);
Variable of data type
161
Additional Needs: Manage Test Variations
n
Tests need to introduce class variations, e.g.
l
l
Adding constraints
Modify the way data is sent by the driver
Instance based variation or global
Control object allocation in entirety or for specific
objects
Create generic functionality
l
Deferring exact object creation to runtime
Solution : Built-in UVM Factory
162
Test Requirements: Transaction
n
How to manufacture transaction instances with
additional information without modifying the
original source code?
class driver extends uvm_driver #(transaction);
...
virtual task run_phase(uvm_phase phase);
forever begin
Type of object
transaction tr;
Poor coding style
determines
tr = new("tr");
No way of overriding
memory allocated
...
the transaction
process(tr);
for the instance
end
object with a derived
endtask
type
endclass
Impossible to add
new members or
modify constraint
later
class my_transaction extends transaction;
int serial_no;
constraint test_constraint {...}
endclass
163
Test Requirements: Components
n
How to manufacture component instances with
additional information without modifying the
original source code?
class environment extends uvm_env;
sequencer seqr;
driver drv;
...
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
No way of modifying
seqr = new("seqr", this);
drv = new("drv", this);
the component
...
behavior
endfunction
endclass
class NewDriver extends driver;
virtual task run_phase(uvm_phase phase);
if ([Link] == 1)
Impossible to
...
change behavior
endtask
endclass
test
for
164
Factories in UVM
Implementation flow
n
Factory instrumentation/registration
l
`uvm_object_utils(Type)
`uvm_component_utils(Type)
Macro creates a proxy class
l
to represent the
object/component called
type_id
And, registers an instance of
n Construct object using static proxy
the proxy
class
in
class
method
uvm_factory
l ClassName obj = ClassName::type_id::create();
n
Class overrides
l
l
set_type_override ();
set_inst_override ();
Use proxy class to create
object
Proxy class in uvm_factory can
be overridden to create
modified object
165
Transaction Factory
n
Construct object via create() in factory class
class packet extends uvm_sequence_item;
rand bit[3:0] sa, da;
`uvm_object_utils_begin(packet)
...
endclass
Required!
Macro defines a proxy class called type_id
An instance of proxy class is registered in
uvm_factory
class bfm extends uvm_component;
Parent handle in proxy
task run_phase(uvm_phase phase);
create() method call
forever begin
a component
packet tr;
tr = packet::type_id::create("tr", this);
...
end
Use create() method of proxy
endtask
class in run phase to construct
endclass
transaction object
must be
166
UVM Factory Transaction Creation
class packet extends uvm_sequence_item;
rand bit[3:0] sa, da;
`uvm_object_utils_begin(packet)
[Link]
...
endclass
macro expansion
class packet extends uvm_sequence_item;
typedef uvm_component_registry #(packet, "packet") type_id;
...
endclass
Parent component handle establishes
search path
packet tr;
tr = packet::type_id::create("tr", this);
Are any overrides of class packet?
newPkt ord = new("tr");
tr = ord;
N
tr = new("tr");
167
Customize Transaction in Test
n
Globally change all packet type
class newPkt extends packet;
int serial_no;
constraint test_constraint {...}
Make modifications
to existing
transaction
Required!
Creates proxy class
`uvm_object_utils_begin(newPkt)
...
endclass class packet_test extends test_base;
`uvm_component_utils(packet_test)
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
set_type_override("packet", newPkt");
endfunction
endclass
all existing
packet
proxypath
to newPkt
Or change just Change
instances
found
in search
set_inst_override(*.[Link], packet, newPkt);
Search path
168
Component Factory
n
Construct object via create() in factory class
class driver extends uvm_driver #(packet);
`uvm_component_utils_begin(driver)
...
endclass
Required!
Macro defines a proxy class called type_id
An instance of proxy class is registered in
uvm_factory
class router_env extends uvm_env;
`uvm_component_utils_begin(router_env)
driver drv;
...
parent handle
function void build_phase(uvm_phase phase);
super.build_phase(phase);
required!
drv = driver::type_id::create("drv", this);
...
endfunction
Use create() method of
endclass
proxy class to construct
component object
169
UVM Factory Component Creation
class driver extends uvm_driver #(packet);
`uvm_component_utils(driver)
...
[Link]
endclass
class driver extends uvm_driver #(packet);
typedef uvm_component_registry #(driver, "driver") type_id;
...
macro expansion
N
endclass
router_env.sv
driver drv;
drv = driver::type_id::create("drv", this);
Any overrides of class driver
under this parent scope?
newDrv ord;
ord = new("drv", this);
drv = ord;
drv = new("drv", this);
170
Customize Component in Test
n
Globally change all driver type
Required!
Creates proxy class
class newDriver extends driver;
`uvm_component_utils_begin(newDriver)
virtual task run_phase();
Make
if ([Link] == 1)
...
behavioral
endtask
modifications
endclass
class component_test extends test_base;
`uvm_component_utils(component_est)
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
set_type_override("driver", "newDriver");
endfunction
endclass
n
Change all existing driver
Or change just instances found in search path
set_inst_override("*.drv", "driver", "newDriver");
Search path
171
Command-line Override
n
User can override factory objects at command line
l
Objects must be constructed with the factory
class_name::type_id::create() method
+uvm_set_inst_override=<req_type>,<override_type>,<inst_path>
+uvm_set_type_override=<req_type>,<override_type>
Works like the overrides in the factory
l
l
set_inst_override()
set_type_override()
Example:
+uvm_set_inst_override=driver,NewDriver,*.drv0
+uvm_set_type_override=packet,newPacket
No space character!
172
Visually Inspect Structural Correctness
n
Topology of the test can be printed with
uvm_top.print_topology()
UVM_INFO @ 734950.0ns: reporter [UVMTOP] UVM testbench topology:
---------------------------------------------------------------------Name
Type
Size
Value
---------------------------------------------------------------------uvm_test_top
test_base
@15
env
router_env
@18
drv_agent_0
driver_agent
@21
drv
driver
@755
rsp_port
uvm_analysis_port
@759
sqr_pull_port
uvm_seq_item_pull_+ @757
router_vi
router_port_wrapper @17
port_id
integral
32
'h0
mon
iMonitor
@789
analysis_port
uvm_analysis_port
@791
port_id
integral
32
'h0
router_vi
router_port_wrapper @17
...
function void final_phase(uvm_phase phase);
uvm_top.print_topology();
endfunction
173
Can Choose Print Format
n
Topology can also be printed in tree format
UVM_INFO @ 734950.0ns: reporter [UVMTOP] UVM testbench topology:
uvm_test_top: (test_base@15) {
env: (router_env@18) {
drv_agent_0: (driver_agent@21) {
drv: (driver@755) {
rsp_port: (uvm_analysis_port@759) {
}
sqr_pull_port: (uvm_seq_item_pull_port@757) {
}
router_vi: (router_port_wrapper@17) {
}
port_id: 'h0
}
mon: (iMonitor@789) {
analysis_port: (uvm_analysis_port@791) {
}
port_id: 'h0
router_vi: (router_port_wrapper@17) {
}
function void final_phase(uvm_phase phase);
}
uvm_top.print_topology(uvm_default_tree_printer);
...
174
Visually Inspect Factory Overrides
n
You should always check the overrides with
[Link]()
n
n
Instance overrides are under Instance Overrides
Global type overrides are under Type Overrides
Instance Overrides:
Requested Type
----------------uvm_sequence_item
Override Path
-------------------------------uvm_test_top.[Link]*.item
Override Type
------------simple_item
Type Overrides:
Requested Type
----------------simple_driver
Override Type
-------------delayed_driver
function void final_phase(uvm_phase phase);
uvm_top.print_topology(uvm_default_tree_printer);
[Link]();
endfunction
175
Best Practice in Extending Components
n
Anticipate that components may be extended to
provide additional functionality
Divide base class into smaller virtual methods that
can be extended and reused
class driver extends uvm_driver #(transaction);
virtual task process(transaction tr);
case ([Link])
READ: read(tr);
WRITE: write(tr); class new_driver extends driver;
endcase
virtual task process(transaction tr);
endtask
case ([Link])
virtual task read(transaction
tr);
INTERRUPT:
interrupt(tr);
virtual task write(transaction
tr);
default:
[Link](tr);
endclass
endtask
virtual task INTERRUPT(transaction tr);
endclass
176
Unit Objectives Review
Having completed this unit, you should be able to:
n
Describe component logical hierarchy
Use logical hierarchy to get/set component
configuration fields
Use factory to create test replaceable transaction
and components
177
Appendix
SystemVerilog Interface
Command Line Configuration
uvm_component_utils Macro
178
SystemVerilog Interface
179
Physical Interface: SystemVerilog Interface
n
Use an interface with a clocking block
l
l
l
Drive signals on clock boundaries
Encapsulate clock details inside interface
Connect TB to IFC with absolute hierarchical reference
interface apb_if(input PClk);
logic [31:0] Addr;
logic [31:0] WData;
logic [31:0] RData;
logic Valid, Write;
clocking master_cb @(posedge PClk);
output Addr;
output WData;
input
RData;
output Valid;
output Write;
endclocking
modport master(clocking master_cb);
endinterface
module top;
bit clk;
apb_if ifc(clk);
dut dut(ifc);
test tb();
endmodule
TB
Physical
Interface
DUT
Interface
top.v
Absolute
hierarchical
reference
180
What is a Virtual Interface?
n
A virtual interface is a pointer to a physical interface
l
n
n
ref router_io sigs; // Psuedo-code
RTL connects blocks with physical interfaces
Testbench drives and samples these interfaces
l
l
Think of it as:
Testbench class objects can not create interfaces
Virtual interface is needed to point to interfaces in RTL
Virtual interface separates testbench from RTL
l
l
Testbench use virtual interface to access RTL signals
Testbench classes are design independent
class router_vi_wrapper extends uvm_object;
virtual router_io sigs;
`uvm_object_utils(router_vi_wrapper)
function new(string name=, virtual router_io sigs=null);
[Link](name);
[Link] = sigs;
endfunction
endclass
181
Command Line Configuration
182
Command-Line Configuration
n
User can configure integer and string at command line
l
Fields must be listed in the uvm_component_utils macro
+uvm_set_config_int=<comp>,<field>,<value>
+uvm_set_config_string=<comp>,<field>,<value>
n
Example:
+uvm_set_config_int=uvm_test_top.*.drv,delay,10
CAUTION:
Only for integer and string!
No space character!
Only for components!
Does not work if uvm_config_db::set() is called!!!!!!
183
uvm_component_utils Macro
184
uvm_component_utils Macros
`uvm_component_utils[_begin](cname)
n Implements the following:
typedef uvm_component_registry #(cname, cname) type_id;
const static string type_name = cname;
static function type_id get_type();
virtual function uvm_object_wrapper get_object_type();
virtual function string get_type_name();
class uvm_component_registry #(type T=uvm_component, string Tname="<unknown>) extends
uvm_object_wrapper;
typedef uvm_component_registry #(T,Tname) this_type;
const static string type_name = Tname;
local static this_type me = get();
static function this_type get();
if (me == null) begin
uvm_factory f = uvm_factory::get();
Macro creates a proxy class
me = new;
which is registered in the
[Link](me);
end
uvm_factory
return me;
endfunction
static function T create(string name="", uvm_component parent=null, string contxt="");
static function void set_type_override(uvm_object_wrapper override_type, bit replace=1);
static function void set_inst_override(uvm_object_wrapper override_type, string inst_path, uvm_component
parent=null);
virtual function string get_type_name();
185
186
Agenda: Day 2
DAY
2
Component Configuration & Factory
TLM Communication
Scoreboard & Coverage
UVM Callback
187
Unit Objectives
After completing this unit, you should be able to:
n
Describe and implement TLM port/socket for
communication between components
188
Component Interface: Overview
n
Need to exchange transactions between
components of verification environment
l
l
Sequencer Driver
Monitor Collectors (Scoreboard, Coverage)
Component
Interfaces
Component
Interfaces
Stimulus
Sequencer
Driver
Coverage
Scoreboard
Monitor
Monitor
Response
Sequencer
Slave
189
Component Interface: Method Interface
n
Component can embed method for communication
class Consumer extends uvm_component;
...
virtual task put(transaction tr);
endclass
But, the interface method should not be called through
the component objects handle
l
Code becomes too inflexible for testbench structure
u
In example below, Producer is stuck with communicating with
only a specific Consumer type
Producer
[Link](tr);
Dont Do
Consumer
task put();
190
Component Interface: Method Interface
n
Use an intermediary interface object (TLM) to
handle the execution of the procedural interface
Call interface
method through
an interface
object
Producer
[Link](tr);
Producer
tlm_port.put(tr);
Consumer
put(tr)
task put();
TLM port
Consumer
task put();
191
Component Interface: Method Interface
n
Through the intermediary interface object (TLM)
components can be re-connected to any other
component on a testcase by testcase basis
Other_Producer
tlm_port.put(tr);
TLM port
Producer
tlm_port.put(tr);
Consumer
task put();
TLM port
Consumer
Producer
task put();
tlm_port.put(tr);
TLM port
Other_Consumer
task put();
192
Communication in UVM: TLM 1.0, 2.0
n
TLM Classes
l uvm_*_export
l uvm_*_imp
l uvm_*_port
l uvm_*_fifo
l uvm_*_socket
simple_env
simple_sequencer
simple_sequence
default_sequence
simple_item
simple_driver
193
UVM TLM 1.0
n
Push
Pull
put_producer
get_producer
put()
get()
put_consumer
get_consumer
Fifo
producer
fifo
consumer
nOne-to-One
Analysis
(broadcast)
write_producer
write()
write_subscriber
write_subscriber
One-to-Many
Many-to-One
write_subscriber
194
Push Mode
n
Push mode
put_producer
put()
put_consumer
class producer extends uvm_component; ...
uvm_blocking_put_port #(packet) put_port;
virtual task main_phase(uvm_phase phase); ...
put_port.put(tr);
endtask
class consumer extends uvm_component; ...
endclass
uvm_blocking_put_imp #(packet, consumer) put_export;
virtual task put(packet tr);
process_tr(tr);
endtask
endclass
class environment extends uvm_env; ...
producer p; consumer c;
virtual function void connect_phase(uvm_phase phase);
p.put_port.connect(c.put_export); // connection required!
endfunction
endclass
195
Pull Mode
n
Pull mode
get_producer
get()
get_consumer
class producer extends uvm_component; ...
uvm_blocking_get_imp #(packet, producer) get_export;
virtual task get(output packet tr);
tr = packet::type_id::create(tr, this);
endtask
class consumer extends uvm_component; ...
endclass
uvm_blocking_get_port #(packet) get_port;
virtual task main_phase(uvm_phase phase); ...
get_port.get(tr);
endtask
endclass
class environment extends uvm_env; ...
producer p; consumer c;
virtual function void connect_phase(uvm_phase phase);
c.get_port.connect(p.get_export); // connection required!
endfunction
endclass
196
FIFO Mode
n
FIFO Mode
Connect producer to consumer via uvm_tlm_fifo
producer
uvm_tlm_fifo
consumer
class environment extends uvm_env; ...
producer p;
consumer c;
uvm_tlm_fifo #(packet) tr_fifo;
virtual funtion void build_phase(uvm_phase phase);
p = producer::type_id::create(p, this);
c = consumer::type_id::create(c, this);
tr_fifo = new(tr_fifo, this); // No proxy (type_id) for TLM ports
endfunction
virtual function void connect_phase(uvm_phase phase);
p.put_port.connect(tr_fifo.put_export); // connection required!
c.get_port.connect(tr_fifo.get_export); // connection required!
endfunction
endclass
197
Analysis Port
n
Analysis
write_producer
(broadcast)
l
write()
Analysis port can be left unconnected
write_subscriber
write_subscriber
class producer extends uvm_component; ...
uvm_analysis_port #(packet) analysis_port;
virtual task main_phase(uvm_phase phase); ...
analysis_port.write(tr);
endtask
class subscriber extends uvm_component; ...
endclass
uvm_analysis_imp #(packet, subscriber) analysis_export;
virtual function void write(packet tr); // required!
process_transaction(tr);
endfunction
endclass
class
environment extends uvm_env; ...
producer p; subscriber s0, s1; // other subscribers
virtual function void connect_phase(uvm_phase phase); ...
p.analysis_port.connect(s0.analysis_export);
p.analysis_port.connect(s1.analysis_export);
endfunction
endclass
198
Port Pass-Through
n
Connecting sub-component TLM ports
l
Use same port type
agent
monitor
write()
scoreboard
class monitor extends uvm_monitor; // other code not shown ...
uvm_analysis_port #(packet) analysis_port;
virtual function void build_phase(uvm_phase phase); ...
this.analysis_port = new("analysis_port", this);
endfunction
endclass
class agent extends uvm_agent; // other code not shown ...
monitor mon;
uvm_analysis_port #(packet) analysis_port;
virtual function void connect_phase(uvm_phase phase);
this.analysis_port = mon.analysis_port;
endfunction
class environment extends uvm_env; ...
endclass scoreboard sb; agent
virtual function void connect_phase(...); ...
agent.analysis_port.connect(sb.analysis_export);
endfunction
endclass
199
UVM TLM 2.0
n
Blocking
b_transport(tx,delay)
initiator
target
Non-Blocking
nb_transport(tx,p,delay)
initiator
target
200
Blocking Transport Initiator
b_transport(tx, delay)
initiator
target
class initiator extends uvm_component;
uvm_tlm_b_initiator_socket #(packet) i_socket;
// constructor not shown
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
i_socket=new(i_socket, this);
endfunction
virtual task main_phase(uvm_phase phase);
packet tx = packet::type_id::create(tx, this);
uvm_tlm_time delay = new();
i_socket.b_transport(tx, delay);
$display(realtime = %t, delay.get_realtime(1ns));
endtask
endclass
201
Blocking Transport Target
b_transport(tx,delay)
initiator
target
class target extends uvm_component; ...
uvm_tlm_b_target_socket #(target, packet) t_socket;
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
t_socket=new("t_socket", this);
endfunction
virtual task b_transport(packet tx, uvm_tlm_time delay);
#10ns;
[Link]();
[Link](10ns, 1ns);
endtask class environment extends uvm_env;
endclass
initiator intr;
target
trgt;
// component_utils, constructor and build_phase not shown
virtual function void connect_phase(uvm_phase phase);
intr.i_socket.connect(trgt.t_socket);
endfunction
endclass
202
Non-Blocking Transport Initiator
nb_transport_fw(tx, p, delay)
initiator
nb_transport_bw(tx, p, delay)
target
class initiator extends uvm_component;
uvm_tlm_nb_initiator_socket #(initiator, packet) i_socket;
// component_utils, constructor and build_phase not shown
virtual task main_phase(uvm_phase phase);
uvm_tlm_sync_e sync; uvm_tlm_phase_e p; uvm_tlm_time delay = new;
packet tx = packet::type_id::create("tx", this);
phase.raise_objection(this);
[Link]();
sync = i_socket.nb_transport_fw(tx, p, delay);
phase.drop_objection(this);
endtask
virtual function uvm_tlm_sync_e nb_transport_bw(packet tx,
ref uvm_tlm_phase_e p, input uvm_tlm_time delay);
// ... Process acknowledgement from target
return (UVM_TLM_COMPLETED);
endfunction
endclass
203
Non-Blocking Transport Target
nb_transport_fw(tx, p, delay)
initiator
nb_transport_bw(tx, p, delay)
target
class target extends uvm_component;
uvm_tlm_nb_target_socket #(target, packet) t_socket;
// component_utils, constructor and build_phase not shown
virtual function uvm_tlm_sync_e nb_transport_fw(packet tx,
ref uvm_tlm_phase_e p, input uvm_tlm_time delay);
[Link]();
return (UVM_TLM_ACCEPTED);
fork process(tx); join_none // for delayed acknowledgement
endfunction
virtual task process (packet tx);
uvm_tlm_sync_e sync; uvm_tlm_phase_e p; uvm_tlm_time delay = new;
// ... After completion of tx processing
sync = t_socket.nb_transport_bw(tx, p, delay);
endtask
endclass
204
UVM Transaction Debug
n
Automatic transaction tracing
l
l
l
Parent/Child relationship
Identify cause-and-effect, request-response
Identify execution stream and start/end time
Environment debug
l
l
l
l
From child to parent, parent to each child
From one side of a connection to another
By hierarchical name (Absolute, Relative)
Components internal state debug
205
UVM Transaction Debug
For VCS 2011-03 onwards
n
Compile-time switches:
l
l
l
+define+UVM_TR_RECORD
-ntb_opts uvm-1.0
-debug or -debug_pp or debug_all
Run-time control:
l
+UVM_TR_RECORD for transaction recording
u
visualize transactions in time on waveform
+UVM_LOG_RECORD for log message recording
u
visualize log messages within components on waveform
206
UVM Transaction Debug in DVE
Slave transaction Stream
Tooltip reveals details
Master transaction
stream
Hierarchical
Transaction View
207
Debugging UVM Transaction Log Messages
Log stream
Tooltip reveals details
Transaction
stream
208
Getting Help on DVE
DVE user guide:
l
DVE tutorial:
l
$VCS_HOME/doc/UserGuide/pdf/dve_ug.pdf
$VCS_HOME/gui/dve/examples/tutorial
UVM transaction debugging examples
l
$VCS_HOME/doc/examples/uvm/xbus_tr_record/examples
209
Unit Objectives Review
Having completed this unit, you should be able to:
n
Describe and implement TLM port/socket for
communication between components
210
Lab 4 Introduction
Implement & configure physical device drivers
30 min
Add virtual
interface to driver
and reset sequence
Configure virtual
interface in Test
Compile
and
Simulate
211
Appendix
TLM 2.0 Generic Payload
212
TLM 2.0 Generic Payload (1/4)
n
TLM 2.0 Generic Payload is a generic bus read/write
access transaction type
l
Used for cross-platform interoperability (e.g. SystemC)
typedef enum {
UVM_TLM_READ_COMMAND,
UVM_TLM_WRITE_COMMAND,
UVM_TLM_IGNORE_COMMAND
} uvm_tlm_command_e;
// Bus read operation
// Bus write operation
// No bus operation
typedef enum {
UVM_TLM_OK_RESPONSE = 1,
// Bus operation completed succesfully
UVM_TLM_INCOMPLETE_RESPONSE = 0,
// Transaction was not delivered to
target
UVM_TLM_GENERIC_ERROR_RESPONSE = -1,
// Bus operation had an error
UVM_TLM_ADDRESS_ERROR_RESPONSE = -2, // Invalid address specified
UVM_TLM_COMMAND_ERROR_RESPONSE = -3, // Invalid command specified
UVM_TLM_BURST_ERROR_RESPONSE = -4,
// Invalid burst specified
UVM_TLM_BYTE_ENABLE_ERROR_RESPONSE = -5 // Invalid byte enabling specified
} uvm_tlm_response_status_e;
213
TLM 2.0 Generic Payload (2/4)
class uvm_tlm_generic_payload extends uvm_sequence_item;
rand bit [63:0]
m_address;
rand uvm_tlm_command_e
m_command;
rand byte unsigned
m_data[];
rand int unsigned
m_length;
// Number of bytes to be copied to or from
// the m_data array
rand uvm_tlm_response_status_e
m_response_status;
rand byte unsigned
m_byte_enable[];
// Indicates valid m_data array elements
rand int unsigned
m_byte_enable_length;
// Number of elements in
m_byte_enable array
rand int unsigned
m_streaming_width; // Number of bytes transferred on each
beat
`uvm_object_utils_begin(uvm_tlm_generic_payload)
`uvm_field_int(m_address, UVM_ALL_ON);
`uvm_field_enum(uvm_tlm_command_e, m_command, UVM_ALL_ON);
`uvm_field_array_int(m_data, UVM_ALL_ON);
`uvm_field_int(m_length, UVM_ALL_ON);
`uvm_field_enum(uvm_tlm_response_status_e, m_response_status, UVM_ALL_ON);
`uvm_field_array_int(m_byte_enable, UVM_ALL_ON);
`uvm_field_int(m_streaming_width, UVM_ALL_ON);
`uvm_object_utils_end
Continued on next slide
214
TLM 2.0 Generic Payload (3/4)
function new(string name="");
virtual function uvm_tlm_command_e get_command();
virtual function void set_command(uvm_tlm_command_e command);
virtual function bit is_read();
virtual function void set_read();
virtual function bit is_write();
virtual function void set_write();
virtual function void set_address(bit [63:0] addr);
virtual function bit [63:0] get_address();
virtual function void get_data (output byte unsigned p []);
virtual function void set_data(ref byte unsigned p []);
virtual function int unsigned get_data_length();
virtual function void set_data_length(int unsigned length);
virtual function int unsigned get_streaming_width();
virtual function void set_streaming_width(int unsigned width);
virtual function void get_byte_enable(output byte unsigned p[]);
virtual function void set_byte_enable(ref byte unsigned p[]);
virtual function int unsigned get_byte_enable_length();
virtual function void set_byte_enable_length(int unsigned length);
virtual function uvm_tlm_response_status_e get_response_status();
virtual function void set_response_status(uvm_tlm_response_status_e status);
virtual function bit is_response_ok();
virtual function bit is_response_error();
virtual function string get_response_string(); // Continued on next page
215
TLM 2.0 Generic Payload (4/4)
n
TLM 2.0 Generic Payload can be extended to add
additional members
l
Requires implementation of uvm_tlm_extension class
// Continued from previous page
local uvm_tlm_extension_base m_extensions [uvm_tlm_extension_base];
function uvm_tlm_extension_base set_extension(uvm_tlm_extension_base ext);
function int get_num_extensions();
function uvm_tlm_extension_base get_extension(uvm_tlm_extension_base
ext_handle);
function void clear_extension(uvm_tlm_extension_base ext_handle);
function void clear_extensions();
endclass
class uvm_tlm_extension #(type T=int) extends
uvm_tlm_extension_base;
typedef uvm_tlm_extension#(T) this_type;
local static this_type m_my_tlm_ext_type = ID();
function new(string name="");
static function this_type ID();
virtual function uvm_tlm_extension_base get_type_handle();
virtual function string get_type_handle_name();
endclass
216
Agenda: Day 2
DAY
2
Component Configuration & Factory
TLM Communication
Scoreboard & Coverage
UVM Callback
217
Unit Objectives
After completing this unit, you should be able to:
n
Build re-usable self checking scoreboards by using
the in-built UVM comparator classes
Implement functional coverage
218
Scoreboard - Introduction
n Todays
l
l
challenges
Self checking testbenches need scoreboards
Develop a scoreboard once, re-use many times in different
testbenches
Need different scoreboarding mechanisms for different
applications
Must be aware of DUTs data transformation
Solution: UVM scoreboard class extension with tailored
functions for matching expected & observed data:
In-order expects
Data transformation
Built in Analysis Exports in the Comparator classes
219
Scoreboard Data Streams
Any ordered data sequence. Not just packets.
Application
Streams
Networking
Packets in, packets out
DSP
Samples in, samples out
Modems, codecs
Frames in, code samples out
Busses, controllers
Requests in, responses out
DS
act
u al
Arbitrary
transformation
d
ecte
exp
DUT
Any number
of input streams
Any number
of output streams
Arbitrary
routing
Arbitrary
interleaving
220
Scoreboard Implementation
n
Use uvm_in_order_class_comparator for checking
class scoreboard extends uvm_scoreboard; // utils macro and constructor
typedef uvm_in_order_class_comparator #(packet) cmpr_type;
cmpr_type cmpr;
Environment
uvm_analysis_export #(packet) before_export;
Scoreboard
uvm_analysis_export #(packet) after_export;
virtual function void build_phase(uvm_phase phase);
Comparator
super.build_phase(phase);
cmpr = cmpr_type::type_id::create(cmpr, this);
before_export = cmpr.before_export;
after_export = cmpr.after_export;
endfunction
Monitor Monitor
virtual function void report_phase(uvm_phase phase);
`uvm_info(Scoreboard Report,
$sformatf(Matches = %0d, Mismatches = %0d,
cmpr.m_matches, cmpr.m_mismatches), UVM_MEDIUM);
endfunction
endclass
221
Scoreboarding: Monitor
n
Monitors supplies scoreboard with
expected and actual transactions
Embed analysis
Environment
Scoreboard
Comparator
class iMonitor extends uvm_monitor; ...
port
virtual router_io sigs;
uvm_analysis_port #(packet) analysis_port;
// uvm_component_utils macro and constructor
Monitor
virtual function void build_phase(); ...
analysis_port = new(analysis_port, this);
if (!uvm_config_db#(virtual router_io)::get(this, "",
"router_io", sigs))
`uvm_fatal("CFGERR", );
Get DUT
endfunction
interface
virtual task run_phase(uvm_phase phase);
forever begin
packet tr = packet::type_id::create("tr", this);
get_packet(tr);
Pass observed transaction to
analysis_port.write(tr);
collector components via TLM
end
endtask
analysis port
virtual task get_packet(packet tr); ...
endclass
222
Embed Monitor in Agent
n
Agent extends from uvm_agent class
l
l
Contains a driver, a sequencer and a monitor
Contains configuration and other parameters
Two operating modes:
l
Test
Active:
Emulates a device in the
system interfaces with DUT
u Instantiates a driver,
sequencer and monitor
Environment
Scoreboard
Passive:
Operates passively
u Only monitor instantiated
and configured
u
Configure
Master Agent
Generator
Cfg
Slave Agent
Driver
Bus
Monitor
DUT
223
UVM Agent Example
class master_agent extends uvm_agent;
uvm_analysis_port #(packet) analysis_port;
// utils macro and constructor not shown
sequencer seqr;
driver
drv;
Sequencer, Driver and Monitor
iMonitor mon;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
is_active flag is built-in
if (is_active == UVM_ACTIVE) begin
seqr = packet_sequencer::type_id::create("seqr",this);
drv = driver::type_id::create("drv",this);
Create sequencer
end
mon
= iMonitor::type_id::create("mon",this); and driver if active
endfunction
function void connect_phase(uvm_phase phase);
analysis_port = mon.analysis_port;
if(is_active == UVM_ACTIVE)
drv.seq_item_port.connect(seqr.seq_item_export);
endfunction : connect
Connect sequencer to
endclass
driver
224
Using UVM Agent in Environment
n
Agent simplifies environment
l
Easier to maintain and debug
Test Top
Environment
Scoreboard
Configure
class router_env extends uvm_env;
master_agent m_agent;
slave_agent s_agent;
master_agent
slave_agent
scoreboard
sb;
// utils and constructor not shown
virtual function void build_phase();
DUT
super.build_phase(phase);
m_agent = master_agent::type_id::create("m_agent", this);
s_agent = slave_agent::type_id::create("s_agent", this);
sb = scoreboard::type_id::create("sb", this);
uvm_config_db#(uvm_active_passive_enum)::set(this, "m_agent",
"is_active", UVM_ACTIVE);
uvm_config_db#(uvm_active_passive_enum)::set(this, "s_agent",
"is_active", UVM_ACTIVE);
endfunction
virtual function void connect_phase(uvm_phase phase);
m_agent.analysis_port.connect(sb.before_export);
s_agent.analysis_port.connect(sb.after_export);
endfunction
endclass
225
Parameterized Scoreboard
n
Scoreboard can be parameterized
l
Must use uvm_component_param_utils macro
class scoreboard #(type T = packet) extends uvm_scoreboard;
...
uvm_in_order_class_comparator #(T) comparator;
`uvm_component_param_utils_begin(scoreboard #(T))
`uvm_field_object(comparator, UVM_PRINT | UVM_COPY)
`uvm_component_utils_end
...
Macro end stays the same
endclass
In environment, set parameter or use default
class router_env extends uvm_env;
typedef scoreboard #(packet) pkt_scoreboard;
pkt_scoreboard sb;
function void build_phase(uvm_phase phase);
sb = pkt_scoreboard::type_id::create(sb, this);
...
endfunction
endclass
226
Scoreboard: Transformed Transaction
n
If transformation is required
class scoreboard extends uvm_scoreboard; ...
uvm_analysis_export #(packet) before_export;
uvm_analysis_export #(output_type) after_export;
transformer xform;
Use
uvm_algorithmic_comparator
#(packet, output_type, transformer) comparator; algorithmic
function void build_phase(uvm_phase);
comparator
before_export = new(before_export, this);
after_export = new(after_export, this);
xform = transformer::type_id::creat(xform, this);
comp = comp_type::type_id::create(comp, this);
endfunction
Scoreboard
...
Comparator
endclass
uvm_in_order_comparator
class transformer extends uvm_object; ...
function output_type transform (packet tr);
// perform transform
endfunction
endclass
Transformer
transform()
227
Scoreboard: Out-Of-Order
n
User can implement out-of-order scoreboard
`uvm_analysis_imp_decl(_before)
`uvm_analysis_imp_decl(_after)
class scoreboard #(type T = packet) extends uvm_scoreboard;
typedef scoreboard #(T) this_type;
`uvm_component_param_utils(this_type)
uvm_analysis_imp_before #(T, this_type) before_export;
uvm_analysis_imp_after #(T, this_type) after_export;
int m_matches = 0, m_mismatches = 0, m_orphaned = 0;
T pkt_list[$];
function new(string name, uvm_component parent);
[Link](name, parent);
before_export = new("before_export", this);
after_export = new("after_export", this);
endfunction
228
Scoreboard: Out-Of-Order
virtual function void write_before(T pkt);
pkt_list.push_back(pkt);
endfunction
virtual function void write_after(T pkt);
int index[$];
index = pkt_list.find_index() with ([Link] == [Link]);
foreach(index[i]) begin
if ([Link](pkt_list[index[i]]) begin
`uvm_info(Packet Match", pkt.get_name(), UVM_MEDIUM);
m_matches++;
pkt_list.delete(index[i]);
return;
end
end
`uvm_warning(Packet Not Found, {\n, [Link]()});
m_orphaned++;
endtask
endclass
229
Functional Coverage
n
Measure the random stimulus to track progress
towards verification goal
What to measure?
l
Configuration: Has testbench tried all legal environment
possibilities?
u
Stimulus: Has testbench generated all representative
transactions, including errors?
u
N drivers, M Slaves, bus addresses, etc.
Reads, writes, interrupts, long packets, short bursts,
overlapping operations
Correctness: Has DUT responded correctly to the
stimulus?
u
Reads, writes, interrupts, long packets, short bursts,
overlapping operations
230
Connecting Coverage to Testbench
n
SystemVerilog Testbench Structure
Cover
Configuration
Testcase
Configure
Coverage
Generator
Coverage
Master
Self Check
Physical
device driver
Bus
Monitor
Cover
Stimulus
Cover
Correctness
Slave
Bus
Monitor
Physical
device driver
DUT
231
Configuration Coverage
covergroup router_cfg_cg(); endgroup
class config_coverage extends uvm_component;
bit coverage_enable = 0;
router_cfg cfg; router_cfg_cg cfg_cg;
`uvm_component_utils_begin(config_coverage)
`uvm_field_object(cfg, UVM_DEFAULT)
`uvm_field_int(coverage_enable, UVM_DEFAULT)
`uvm_component_utils_end;
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (coverage_enable) begin
if (!uvm_config_db #(router_cfg)::get(this, "", "cfg", cfg) begin
`uvm_fatal();
end
cfg_cg = new();
end
endfunction
virtual function void end_of_elaboration_phase(uvm_phase phase);
if (coverage_enable)
cfg_cg.sample(cfg.num_of_active_ports);
endfunction
endclass
232
Configuration Coverage
n
Build configuration coverage component in test
class test_ports extends test_base;
router_cfg cfg;
config_coverage cfg_cov;
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
cfg = router_cfg::type_id::create("cfg", this);
if (![Link]()) begin
`uvm_fatal();
end
uvm_config_db #(router_cfg)::set(this, "cfg_cov", "cfg", cfg);
uvm_config_db #(int)::set(this, "cfg_cov", "coverage_enable", 1);
cfg_cov = config_coverage::type_id::create("cfg_cov", this);
endfunction
endclass
233
Stimulus Coverage
covergroup packet_cg with function sample(bit [3:0] sa);
coverpoint sa;
endgroup : packet_cg
class packet_coverage extends uvm_component;
bit coverage_enable = 0;
Packet cover
packet_cg pkt_cg;
group
`uvm_component_utils_begin(packet_coverage)
`uvm_field_int(coverage_enable, UVM_DEFAULT)
`uvm_component_utils_end;
uvm_analysis_imp #(packet, packet_coverage) cov_export;
TLM
virtual function void build_phase(uvm_phase phase);
connection to
super.build_phase(phase);
monitor
cov_export = new("export", this);
if (coverage_enable) pkt_cg = new();
Export method
endfunction
called with
function void write(packet p);
monitored packets
if (coverage_enable) pkt_cg.sample([Link]);
endfunction : write
endclass
234
Correctness Coverage
covergroup packet_sb_cg with function sample(bit [3:0] sa, da);
coverpoint sa;
coverpoint da;
cross sa, da;
endgroup : packet_sb_cg
`uvm_analysis_imp_decl(_before)
`uvm_analysis_imp_decl(_after)
class scoreboard #(type T = packet) extends uvm_scoreboard;
bit coverage_enable = 0;
Packet cover
packet_sb_cg pkt_cg;
group
// component_utils and other code
Export method
virtual function void write_after(T pkt);
...;
called with
if ([Link](pkt_ref) begin
monitored packets
m_matches++;
if (coverage_enable) pkt_cg.sample(pkt_ref.sa, pkt_ref.da);
end else begin
m_mismatches++;
end
...;
endfunction : write_after
endclass
235
Unit Objectives Review
Having completed this unit, you should be able to:
n
Build re-usable self checking scoreboards by using
the in-built UVM comparator classes
Implement functional coverage
236
Appendix
Multi-Stream Scoreboard
237
Scoreboard: Multi-Stream
`uvm_analysis_imp_decl(_before)
`uvm_analysis_imp_decl(_after)
class scoreboard #(type T = packet, int num=16) extends uvm_scoreboard;
typedef scoreboard #(T) this_type;
`uvm_component_param_utils(this_type)
uvm_analysis_imp_before #(T, this_type) before_export;
uvm_analysis_imp_after #(T, this_type) after_export;
uvm_analysis_port #(T) comparator_before_port[num];
uvm_analysis_port #(T) comparator_after_port[num];
uvm_in_order_class_comparator #(T) comparator[num];
function new (string name, uvm_component parent);
[Link](name, parent);
before_export = new(before_export, this);
after_export = new(after_export, this);
for (int i=0; i < num; i++) begin
comparator[i] = new($sformatf(comparator_%0d, i), this);
comparator_before_port[i] =
new($sformatf(comparator_before_port_%0d, i), this);
comparator_after_port[i] =
new($sformatf(comparator_after_port_%0d, i), this);
end
endfunction
... // Continued on next page
238
Scoreboard: Multi-Stream
virtual function void connect_phase(uvm_phase phase);
for (int i=0; i < num; i++) begin
comparator_before_port[i].connect(comparator[i].before_export);
comparator_after_port[i].connect(comparator[i].after_export);
end
endfunction
virtual function void write_before(T pkt);
comparator_before_port[[Link]].write(pkt);
endfunction
virtual function void write_after(T pkt);
comparator_after_port[[Link]].write(pkt);
endfunction
endclass
239
240
Agenda: Day 2
DAY
2
Component Configuration & Factory
TLM Communication
Scoreboard & Coverage
UVM Callback
241
Unit Objectives
After completing this unit, you should be able to:
n
Build faade callback classes
Embed callback methods
Implement callback to inject errors
Implement callback to implement coverage
242
Changing Behavior of Components
n
How to add new functionality to a component?
l
Extend existing component class
class error_driver extends my_driver;
virtual task send();
endclass
driver_coverage
?
delay_driver
?
l
How to add multiple extensions?
error_driver
delay_driver
class delay_driver extends my_driver;
?
class delay_driver extends error_driver;
driver
Multiple extensions can cause unstable OOP hierarchy
Use callbacks to add new capabilities, without
creating huge OOP hierarchy
4
3
2
1
243
Implementing UVM Callbacks
n
n
n
n
Embed callback methods in components
Create a faade callback class
Develop callback classes extending from faade callback class
Create and register callback objects in environment
uvm_object class
uvm_callbacks_base class
uvm_component class
Embed
callback
methods
Component class
Create and
register in Test
User callback faade class
Create
faade
class
4
Coverage callback class
Test class
uvm_callbacks class
Error Injection callback class
Implement callback methods
244
Step 1: Embed Callback Methods
n
Typically before and/or after major operation
1a. Register callback
class driver extends uvm_driver #(packet);
with component
`uvm_register_cb(driver, driver_callback)
// utils macro and constructor not shown
task run_phase(uvm_phase phase);
1b. Embed callback methods
forever begin
with uvm_do_callbacks
seq_item_port.get_next_item(req); macro
`uvm_do_callbacks(driver, driver_callback, pre_send(this, req));
send(req);
Callback class name
User must create (see next slide)
component class
name
`uvm_do_callbacks(driver, driver_callback, post_send(this, req));
seq_item_port.item_done();
end
Callback method
endtask
User must embed in callback class (see next
endclass
slide)
245
Step 2: Declare the faade Class
n
Create faade class called in uvm_do_callbacks macro
l
l
l
Typically declared in same file as the component
All methods must be declared as virtual
Leave the body of methods empty
2. Create callback faade class
class driver_callback extends uvm_callback;
function new(string name = driver_callback);
[Link](name);
Empty body: noop
endfunction
virtual task pre_send(driver drv, packet tr); endtask
virtual task post_send(driver drv, packet tr); endtask
endclass
Argument types must match
types in `uvm_do_callbacks()
macro
246
Step 3: Implement Callback: Error
n
Create error class by extending from faade class
l
Embed error in callback method
3. Implement error callback
class driver_err_callback extends driver_callback;
virtual task pre_send(driver drv, packet tr);
[Link]();
endtask
endclass
247
Step 4: Create and Register Callback Objects
n
Instantiate the callback object in test
Construct and register callback object
class driver_err_test extends test_base;
// utils macro and constructor not shown
driver_err_callback drv_err_cb;
4a. Create callback objects
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
4b. Register callback objects
drv_err_cb = new();
uvm_callbacks #(driver, driver_callback)::add([Link], drv_err_cb);
uvm_callbacks #(driver, driver_callback)::display();
endfunction
endclass
4c. Visually verify the registration (optional)
248
Driver Coverage Example
n
If there are no analysis ports in driver
l
Callbacks can be the hooks for coverage also
typedef class driver;
class driver_callback extends uvm_callback;
// constructor not shown
virtual task pre_send(driver drv, packet tr); endtask
virtual task post_send(driver drv, packet tr); endtask
endclass
class driver extends uvm_driver #(packet);
`uvm_register_cb(driver, driver_callback)
// utils macro and constructor not shown
task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
`uvm_do_callbacks(driver, driver_callback, pre_send(this, req));
send(req);
`uvm_do_callbacks(driver, driver_callback, post_send(this, req));
seq_item_port.item_done();
end
endtask
endclass
249
Implement Coverage via Callback
n
Create coverage class by extending from faade class
l
l
l
Define covergroup in coverage class
Construct covergroup in class constructor
Sample coverage in callback method
3a. Extend faade class
class driver_cov_callback extends driver_callback;
covergroup drv_cov with function sample(packet pkt);
coverpoint [Link]; coverpoint [Link];
cross [Link], [Link];
endgroup
function new();
3b. Implement coverage
drv_cov = new();
endfunction
virtual task post_send(driver drv, packet tr);
drv_cov.sample(tr);
endtask
endclass
250
Create and Register Callback Objects
n
Instantiate the callback object in Environment
Construct and register callback object in build phase
class test_driver_cov extends test_base;
// utils macro and constructor not shown
driver_cov_callback drv_cov_cb;
4a. Create callback objects
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
drv_cov_cb = new();
uvm_callbacks #(driver, driver_callback)::add([Link], drv_cov_cb);
endfunction
endclass
4b. Register callback objects
251
Sequence Callback Methods
n
uvm_sequence::pre_do() (task)
l called after the sequence::wait_for_grant() call and after the
sequencer has selected this sequence, but before the item is
randomized
uvm_sequence::mid_do() (function)
l called after the sequence item randomized, but before it is sent
to driver
uvm_sequence::post_do() (function)
l called after the driver indicates item completion,using
item_done/put
uvm_sequence::pre_body() (task)
l Called before sequence body execution
uvm_sequence::post_body() (task)
l Called after sequence body execution
User should not call
these methods directly.
Instead override in
sequence definition
252
Unit Objectives Review
Having completed this unit, you should be able to:
n
Build faade callback classes
Embed callback methods
Implement callback to inject errors
Implement callback to implement coverage
253
Lab 5 Introduction
Implement monitors and scoreboard
60 min
Implement
Monitor
Classes
Implement
Scoreboard
Class
Compile
and
Simulate
254
Agenda: Day 3
DAY
3
Sequence Library/Virtual Sequencer
10
More on Phasing
11
Register Abstraction Layer
12
Summary
255
Unit Objectives
After completing this unit, you should be able to:
n
Create reusable sequences/sequence library in
UVM
Co-ordinate sequences at multiple interfaces
through Virtual Sequences and Sequencers
256
UVM 1.0 Sequence Library
n
Define related sequences
Base
class base_sequence extends uvm_sequence#(packet);
Atomic
class atomic_seq extends base_sequence;
`uvm_add_to_seq_lib(atomic_seq, packet_seq_lib)
Four
class four_item_seq extends base_sequence;
`uvm_add_to_seq_lib(four_item_seq, packet_seq_lib)
SAeq3
sa
==3
sa
==3
class SAeq3_seq extends base_sequence;
`uvm_add_to_seq_lib(SAeq3_seq, packet_seq_lib)
Group together in a library
class packet_seq_lib extends uvm_sequence_library #(packet);
endclass
257
Building a Sequence Library Package
To enhance reuseability,
encapsulate sequence library
classes in a package
A library class is a
repository of
sequences of a
particular data
type
package packet_seq_lib_pkg;
import uvm_pkg::*;
class packet extends uvm_sequence_item;
...
endclass
class packet_seq_lib extends uvm_sequence_library #(packet);
`uvm_object_utils(packet_seq_lib)
Macro builds the
`uvm_sequence_library_utils(packet_seq_lib)
infrastructure of
function new(string name = "packet_seq_lib");
the sequence
[Link](name);
library
init_sequence_library();
Method allows
endfunction
registration of
endclass
sequences into the
// continued on next page
library
258
Building a Sequence Library
n
Add base sequence and user sequence(s) to package
// continued from previous page
class packet_base_sequence extends uvm_sequence #(packet);
// object_utils macro and constructor not shown
virtual task pre_body();
if (starting_phase != null)
See note
starting_phase.raise_objection(this);
endtask
Extend from base
virtual task post_body();
sequence to
if (starting_phase != null)
starting_phase.drop_objection(this); create user
endtask
sequence
endclass
class atomic_sequence extends packet_base_sequence;
`uvm_object_utils(atomic_sequence)
`uvm_add_to_seq_lib(atomic_sequence, packet_seq_lib)
// Constructor not shown
registers sequence in the
virtual task body();
library
`uvm_do(req);
endtask
endclass
endpackage
259
Register Sequence in Sequence Library
n
Register additional test sequences as needed
class generic_sequence extends packet_sequence;
int item_count = 1; // utils macro and constructor not shown
`uvm_add_to_seq_lib(generic_sequence, packet_seq_lib)
task body();
if (!uvm_resource_db#(int)::read_by_name())
...
repeat(item_count)begin
`uvm_do(req);
end
endtask class SAeq3_sequence extends generic_sequence;
`uvm_object_utils(SAeq3_sequence)
endclass
`uvm_add_to_seq_lib(SAeq3_sequence, packet_seq_lib)
// Constructor not shown
virtual task body();
if (!uvm_resource_db#(int)::read_by_name())
repeat(item_count) begin
`uvm_do_with(req, { sa == 3; } );
end
endtask
endclass
260
Reference Sequence Library in Environment
n
In the environment, make the sequence library the
default sequence for the sequencer
class router_env extends uvm_env;
router_agent agent;
// utils macro and constructor not shown
function void build_phase(uvm_phase phase);
super.build_phase(phase);
agent = router_agent::type_id::create("agent", this);
uvm_config_db #(uvm_object_wrapper)::set(this, "seqr.main_phase",
"default_sequence", packet_seq_lib::get_type());
endfunction
endclass
261
Create Test with Random Sequences
n
By default ten random sequences from the
sequence library will be executed
program automatic test;
import uvm_pkg::*;
import packet_seq_lib_pkg::*;
// include other classes
class test_base extends uvm_test;
router_env env;
// component_utils and constructor not shown
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
env = router_env::type_id::create(env, this);
endfunction
endclass
initial
run_test();
endprogram Compile with vcs: (using UVM in VCS installation)
vcs sverilogntb_opts uvm packet_seq_lib_pkg.sv [Link]
Simulate with:
simv +UVM_TESTNAME=test_base
262
Configure Sequence Library
n
The default execution behavior can be modified via
the UVM uvm_sequence_library_cfg class
class uvm_sequence_library_cfg extends uvm_object;
`uvm_object_utils(uvm_sequence_library_cfg)
uvm_sequence_lib_mode selection_mode;
int unsigned min_random_count, max_random_count;
function new(string name="",
uvm_sequence_lib_mode mode=UVM_SEQ_LIB_RAND,
int unsigned min=1, int unsigned max=10);
endclass
Combination of min_/max_random_count sets the
number of sequences to execute
selection_mode can be one of four modes:
UVM_SEQ_LIB_RAND
(Random sequence)
UVM_SEQ_LIB_RANDC (Random cyclic sequence)
UVM_SEQ_LIB_ITEM (Random item. No sequence)
UVM_SEQ_LIB_USER
(User defined sequence execution)
263
Configure Sequence Library Example
n
In test, set sequence library configuration values
program automatic test;
import uvm_pkg::*;
import seq_lib_pkg::*;
// include other classes
class test_5_seq extends test_base;
uvm_sequence_library_cfg seq_cfg;
// utils macro and constructor not shown
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
seq_cfg = new("seq_cfg", UVM_SEQ_LIB_RAND, 5, 5);
uvm_config_db #(uvm_sequence_library_cfg)::set(this,
*.seqr.main_phase, "default_sequence.config", seq_cfg);
endfunction
endclass
initial
run_test();
endprogram
264
Virtual Sequences
n
When integrating multiple agents into a higher level
block, how can the sequencers in each of these be
managed?
l
Stimulus timing across multiple DUT interfaces may need to
be synchronized
Solution: Virtual Sequences
l
l
l
Helps synchronize the timing and the data across the
different interfaces
Allows fine grained control of the test environment
Doesnt have its own data item, used to control other
sequences and sequence drivers
265
Virtual Sequence/Sequencer
n
Typical sequence interacts with a single DUT interface
When multiple DUT interfaces need to be synchronized
a virtual sequence is required
Virtual Sequences in environment/test synchronize
timing and data between different interfaces
TOP
Environment
Virtual Sequencer
Sequencer
Virtual sequence
Sequencer
sequence
Sequencer
Agent
sequences
M_Driver
sequence
Sequencer
Agent
Sequences
Monitor
M_Driver
Monitor
266
Virtual Sequence
n
n
Embed sequence from different agents
In body() method, control these sequences
class virtual_sequence extends uvm_sequence;
`uvm_object_utils(virtual_sequence)
`uvm_declare_p_sequencer(virtual_sequencer)
bfm_sequence bfm0_seq;
bfm_sequence bfm1_seq;
virtual task body();
`uvm_do_on(bfm0_seq, p_sequencer.bfm0_sqr);
`uvm_do_on(bfm1_seq, p_sequencer.bfm1_sqr);
endtask
Environment
endclass
Virtual Sequencer
bfm0_sqr
bfm1_sqr
bfm_sqr
bfm_seq
Virtual sequence
bfm0_seq
bfm_agt0
bfm1_seq
bfm_sqr
bfm_agt1
bfm_seq
267
Virtual Sequencer
n
Embed sequencers managing the sequences
class virtual_sequencer extends uvm_sequencer; ...
bfm_sequencer bfm0_sqr;
bfm_sequencer bfm1_sqr;
function new(string name, uvm_component parent);
[Link](name, parent);
endfunction
endclass
Environment
Virtual Sequencer
bfm0_sqr
Virtual sequence
bfm1_sqr
bfm_sqr
bfm_seq
bfm_agt0
bfm0_seq
bfm1_seq
bfm_sqr
bfm_agt1
bfm_seq
268
Connect Sequencer to Virtual Sequencer
n
Disable the controlled sequencers
class environment extends uvm_env; ...
virtual_sequencer v_sqr; bfm_agent bfm0_agt, bfm1_agt;
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
// creation of objecs not shown
uvm_config_db#(uvm_object_wrapper)::set(this,
"*.bfm0_agt.sqr.main_phase",
"default_sequence", bfm_base_sequence::get_type());
uvm_config_db#(uvm_object_wrapper)::set(this,
"*.bfm1_agt.sqr.main_phase",
"default_sequence", bfm_base_sequence::get_type());
endfunction
// continued on the next page
Disable child sequencers
Assuming bfm_base_sequence
is noop
269
Connect Sequencer to Virtual Sequencer
n
Connect controlled sequencers to virtual sequencer
// Continued from
virtual function
v_sqr.bfm0_sqr
v_sqr.bfm1_sqr
endfunction
endclass
previous page
void connect_phase(uvm_phase phase);
= bfm_agt0.bfm_sqr;
= bfm_agt1.bfm_sqr
Environment
Virtual Sequencer
bfm0_sqr
Virtual sequence
bfm1_sqr
bfm_sqr
bfm_seq
bfm_agt0
bfm0_seq
bfm1_seq
bfm_sqr
bfm_agt1
bfm_seq
270
Protecting Stimulus (Grab/Ungrab )
n
Sequence can reserve a Sequencer for exclusive use
l
l
Until explicitly released
Other request for exclusive use or stimulus injection will be
blocked
class simple_sequence extends uvm_sequence #(packet);
// utils macro and constructor not shown
Sequence requesting grab()
virtual task body();
reserves parent sequencer for
grab();
exclusive use
repeat(10) begin
`uvm_info(get_name(), "In body()", UVM_HIGH)
`uvm_do_with(req,{addr == 6; data == 6;})
end
ungrab() method releases grab for
ungrab();
default/specified sequencer.
endtask
endclass
271
Unit Objectives Review
Having completed this unit, you should be able to:
n
Create reusable sequences/sequence library in
UVM
Co-ordinate sequences at multiple interfaces
through Virtual Sequences and Sequencers
272
Agenda: Day 3
DAY
3
Sequence Library/Virtual Sequencer
10
More on Phasing
11
Register Abstraction Layer
12
Summary
273
Unit Objectives
After completing this unit, you should be able to:
n
Create synchronized and un-synchronized
phase domains
Create user phases
274
UVM Phasing
build
connect
end_of_elaboration
start_of_simulation
run
reset
configure
main
shutdown
extract
check
report
final
275
Common Phases
build
Create and configure testbench structure
connect
Establish cross-component connections
end_of_elaboration
Fine-tune the testbench
start_of_simulation
Get ready for DUT to be simulated
run
Stimulate the DUT
extract
Extract data from different points of the verification
environment
check
Check for any unexpected conditions in the
verification environment
report
Report results of the test
final
Tie up loose ends
For more details please see UVM Reference Guide
276
Scheduled Run Time Task Phases
pre_reset
Setup/Wait for conditions to reset DUT
reset
Reset DUT
post_reset
Wait for DUT to be at a known state
pre_configure
Setup/Wait for conditions to configure DUT
configure
Configure the DUT
post_configure
Wait for DUT to be at a known configured state
pre_main
Setup/Wait for conditions to start testing DUT
main
Test DUT
post_main
Typically a no-op
pre_shutdown
Typically a no-op
shutdown
Wait for data in DUT to be drained
post_shutdown
Perform final checks that consume simulation time
For more details please see UVM Reference Guide
277
Phase Synchronization
n
All components executing a Run Time phase must
drop objections for that phase before any component
can move on to the next phase
component A
reset
component B
reset
configure
main
component C
reset
configure
main
main
shutdown
shutdown
Reset phase
Configure phase
Main phase
Shutdown phase
278
Phase Objection (1/3)
n
Objection typically raised at stimulus creation
l
Parent sequence
Executes only
if sequence is
the parent
sequence
class packet_sequence ...;
// other code not shown
task pre_body();
if (starting_phase != null)
starting_phase
starting_phase.raise_objection(this); is null if sequence
endtask
is a child
task post_body();
sequence.
if (starting_phase != null)
starting_phase.drop_objection(this);
Must check!
endtask
endclass
Objection set for main
phase
class router_env extends uvm_env;
virtual function void build_phase(uvm_phase phase);
// code not shown
uvm_config_db #(uvm_object_wrapper)::set(agent, "seqr.main_phase",
"default_sequence", packet_sequence::get_type());
endfunction
endclass
279
Phase Objection (2/3)
n
Objection should not be raised/dropped in component's
run or main phase
l
Impacts simulation with excessive objection count
class driver extends ...;
task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
Debug with
phase.raise_objection(this);
+UVM_OBJECTION_TRACE
send(req);
run-time switch
seq_item_port.item_done();
phase.drop_objection(this);
end
class iMonitor extends ...;
endtask
virtual task run_phase(uvm_phase phase);
endclass
forever begin
@(negedge [Link].frame_n[port_id]);
phase.raise_objection(this);
get_packet(tr);
phase.drop_objection(this);
end
endtask
endclass
280
Phase Objection (3/3)
What about latency of outputs?
If monitor/slave do not implement objection, doesn't the
phase terminate before the output sampling is done?
n
Objection dropping can be delayed with drain time
class packet_sequence extends uvm_sequence #(packet);
Get objection
virtual task body();
if (starting_phase != null) begin
handle
uvm_objection objection = starting_phase.get_objection();
objection.set_drain_time(this, 1us);
Set drain time
starting_phase.raise_objection(this);
end
`uvm_do(req);
if (starting_phase != null) begin
starting_phase.drop_objection(this);
end
endtask
endclass
281
Advanced Features
n
User Defined Phases/Schedules
l
Multiple Phase Domains
l
l
Can be mixed with predefined Phases/Schedules
No inter-domain synchronization by default
Full and partial synchronization
Phase Jumping
l
Forwards and Backwards
Only recommended for
(Environment) Implementers
not (Component) Developers
282
User Defined Phase
n
User can create customized phases
User phase
name
Phase name
prefix
`uvm_user_task_phase(new_cfg, driver,
my_)
Component where phase will
execute
Macro creates a new phase class called my_new_cfg_phase
driver must implement new_cfg_phase(uvm_phase
phase)
class environment extends uvm_env; // utils and constructor
function void build_phase(uvm_phase phase);
uvm_domain env_domain = this.get_domain();
super.build_phase(phase);
drv = new(drv, this);
env_domain.add(my_new_cfg_phase::get(),
.after_phase(uvm_configure_phase::get());
endfunction
endclass
Add phase into domain
283
Phase Domains
n
Run Time Phases are organized as domains
l
The default domain name is uvm
task main_phase(uvm_phase phase);
$display(Executing in %s domain", phase.get_domain_name());
User can create customized domains
Created two user domains
class environment extends uvm_env;
driver drv0, drv1;
uvm_domain domain0=new("domain0"), domain1=new("domain1");
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
drv0 = new(drv0", this); drv1 = new(drv1, this);
endfunction
virutal function void connect_phase(uvm_phase phase);
drv0.set_domain(domain0);
drv1.set_domain(domain1);
[Link](this.get_domain());
...
drv1s phases are synchronized with
endfunction
environment
endclass
drv0s phases are independent of all other
284
Phase Jump: Backward
n
Phases can be rolled back
Mid-simulation reset can be accomplished by
jumping back to reset phase
Environment must be designed to support jumping
l
l
l
All active components must implement reset_phase() to
return control signals to de-asserted state
All residual properties must be deleted
All residual processes must be killed
reset
configure
main
shutdown
class test_jump2reset extends test_base;
// code not shown
virtual task post_main_phase();
static int count = 0;
if (count++ < 5)
[Link](uvm_reset_phase::get());
endtask
285
Phase Jump: Forward
n
Useful for a test to skip a behavior
l
Example: skip rest of main if coverage is met
Environment must be designed to support jumping
l
l
Clears objection for phase when called
Shutdown phase must take care of draining testbench and
DUT pipelines before terminating simulation
class driver extends uvm_driver #(...);
event update; covergroup d_cov ...
virtual task run_phase(...);
forever begin
seq_item_port.get_next_item(req);
d_cov.sample(req); -> update;
seq_item_port.item_done();
end
virtual task main_phase(...);
endtask
forever begin
endclass
@(update);
if ($get_coverage() == 100.0)
[Link](uvm_pre_shutdown_phase::get());
end
endtask
286
Unit Objectives Review
Having completed this unit, you should be able to:
n
Create synchronized and un-synchronized phase
domains
Create user phases
287
Lab 6 Introduction
Implement sequence library
30 min
Implement
Sequence
library
Compile
and
Simulate
288
Agenda: Day 3
DAY
3
Sequence Library/Virtual Sequencer
10
More on Phasing
11
Register Abstraction Layer
12
Summary
289
Unit Objectives
After completing this unit, you should be able to:
n
Create ralf file to represent DUT registers
Use ralgen to create UVM register classes
Use UVM register in sequences
Implement adapter to correctly pass UVM
register object to drivers
Run built-in UVM register tests
290
Register & Memories
Every DUT has them
First to be verified
l
l
Reset value
Bit(s) behavior
High maintenance
l
l
Modify tests
Modify firmware model
291
Testbench without RAL
A typical test
check reset value
write value
check value
sequence
body()
device
drivers
Host Sequencer
What about
coverage?
self-checking?
randomization?
portability?
Host Driver
Host Other
Port Ports
address
data
r_w
DUT
register
Memory
HOST_ID
LOCK
REG_FILE
example
register
mapping
Memory
class host_sequence extends uvm_sequence #(host_data); ...;
virtual task body();
`uvm_do_with(req, {addr=='h100; data=='1; kind==host_data::WRITE;});
`uvm_do_with(req, {addr=='h100; kind==host_data::READ;}); ...;
endtask
Address hardcoded!
endclass
Field name unknown!
Status of execution
292
unknown!
Register Abstraction Layer (RAL)
n
Abstracts reading/writing to
configuration fields and
memories
Supports both front door
and back door access
Mirrors register data
Built-in functional coverage
Hierarchical model for ease of
reuse
Pre-defined tests exercise
registers and memories
Simulation
User
tests
Pre-defined
tests
Coverage Model
uvm_reg
Spec
backdoor
frontdoor
RTL
293
Testbench with RAL:
Sequencer
Unchanged
New sequence uses
register models
abstraction to read
and write DUT fields
sequence
body()
Register model
Adapter
Register model with
Built-in:
coverage
self-checking
randomization
portable structure
device
drivers
Driver Unchanged
Host Other
Port Ports
address
data
r_w
DUT
register
Memory
HOST_ID
LOCK
REG_FILE
Memory
class host_sequence extends uvm_sequence #(host_data); ...;
virtual task body(); uvm_status_e status; uvm_reg_data_t data;
regmodel.HOST_ID.read(status, data, UVM_FRONTDOOR, this);
[Link](status, 1, UVM_FRONTDOOR), this);
endtask
Access can be front
Access via abstracted field
endclass
door or back door
name
Status of execution returned
294
Implement RAL in Six Steps
n
Step 1: Create & verify frontdoor BFM without RAL
Step 2: Describe register fields in ralf file
Step 3: Use ralgen to create RAL classes
Step 4: Create RAL adapter
Step 5: Instantiate RAL model in environment
Step 6: Write and run RAL test sequence
Optional: Run built-in test
Pre-defined
tests
Spec
Coverage Model
RAL
Frontdoor
access
RAL
BFM
Backdoor
access
RTL DUT
295
Example Specification
HOST_ID Register
Address Map
sequence
Host Sequencer
body()
HOST_ID
0x0000
Field
CHIP_ID
REV_ID
PORT_LOCK
0x0100
Bits
15-8
7-0
REG_FILE
0x1000-0x10FF
Mode
ro
ro
RAM
0x4000-0x4FFF
Reset
0x5A
0x03
Mode
run_phase
Host Driver
ro
Read Only
rw
Read/Write
w1c
Write 1 to Clear
device
drivers
Host Other
Port Ports
address
data
r_w
DUT
register
Memory
HOST_ID
LOCK
REG_FILE
RAM
PORT_LOCK Register
Field
LOCK
Bits
15-0
Mode
w1c
Reset
0xff
Field
Bits
Mode
Reset
Bits
Mode
Register File
REG_FILE[256]
15-0
rw
0x00
RAM (4K)
15-0
rw
296
Create Host Transaction and Component
sequence
Host Sequencer
body()
run_phase
Host Driver
device
drivers
Host Other
Port Ports
address
data
r_w
DUT
register
Memory
class host_data extends uvm_sequence_item;
// constructor and utils macro not shown
typedef enum int unsigned {
READ,
WRITE
} kind_e;
rand kind_e kind;
rand bit[15:0] addr, data;
endclass: host_data
class host_driver extends uvm_driver
#(host_data);
// constructor and utils macro not shown
task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
data_rw(req); // call device driver
seq_item_port.item_done();
end
endtask
// device drivers not shown;
endclass: host_driver
297
Create Host BFM Sequence
n
sequencer
Implement host sequence
sequence
body()
class host_bfm_sequence extends uvm_sequence #(host_data);
// utils macro and constructor not shown
task body();
if (starting_phase != null) starting_phase.raise_objection(this);
`uvm_do_with(req, {addr==h000; kind==host_data::READ;});
`uvm_do_with(req, {addr==h100; data==1; kind==host_data::WRITE;});
`uvm_do_with(req, {addr==h100; kind==host_data::READ;});
if (starting_phase != null) starting_phase.drop_objection(this);
endtask
endclass
298
Verify Frontdoor Host BFM is Working
class host_env extends uvm_env;
typedef uvm_sequencer #(host_data) host_sequencer;
host_driver
drv;
host_sequencer
seqr;
// constructor and utils macro not shown
function void build_phase(uvm_phase phase);
// super.build_phase and construction of components not shown
uvm_config_db#(uvm_object_wrapper)::set(this,"seqr.configure_phase",
"default_sequence", host_bfm_sequence::type_id::get());
endfunction
// connect_phase not shown
endclass
class test_base extends uvm_test;
host_env h_env;
// constructor and utils macro not shown
function void build_phase(uvm_phase phase);
// super.build_phase and construction of components not shown
uvm_config_db#(virtual host_io)::set(this, "h_env.*", "host_io",
router_test_top.host);
endfunction
endclass
299
Step 2: Create .ralf File Based on Spec
register HOST_ID {
field REV_ID {
bits
8;
access ro;
reset h03;
}
field CHIP_ID {
bits
8;
access ro;
reset h5A;
}}
register PORT_LOCK {
field LOCK {
bits 16;
access w1c;
reset hffff;
}}
regfile REG_FILE {
register HOST_REG {
field USER_REG {
bits 16;
access rw;
reset h0000;
}}}
memory RAM {
size
4k;
bits
16;
access rw;
}
Field
CHIP_ID
REV_ID
Bits
15-8
7-0
Mode
ro
ro
Reset
0x5A
0x03
PORT_LOCK Register
Field
LOCK
Bits
15-0
Mode
w1c
Reset
0xff
Field
Bits
Mode
Reset
register
field
HOST_ID Register
field
regfile
Bits
Mode
Register File
REG_FILE[256]
15-0
rw
0x00
RAM (4K)
15-0
rw
register
register
register
memory
300
Step 2: Create .ralf File Based on Spec
Create register model to be used at block
level
block host_regmodel {
bytes 2;
register HOST_ID
register PORT_LOCK
regfile REG_FILE[256]
memory RAM
}
logic name in
DUT
(host_id)
(lock)
(host_reg[%d])
(ram)
@h0000;
@h0100;
@h1000;
@h4000;
module instance name in
DUT
system dut_regmodel {
bytes 2;
block host_regmodel=HOST0 (blk0) @'h0000;
block host_regmodel=HOST1 (blk1) @'h8000;
}
Optional:
Create register model to be used at system
level
Address Map
HOST_ID
PORT_LOCK
REG_FILE
RAM
0x0000
0x0100
0x1000-0x10FF
0x4000-0x4FFF
system
block
block
register
register
field
field
field
field
memory
memory
register
register
regfile
register
field
field
register
field
register
register
301
RAL File Field Syntax
n
Field
l
Contains Bits, Access, Reset Value, Constraints
field field_name {
[bits n;]
[access rw|ro|wo|w1|w0c|w1c|rc|...;]
[reset value;]
[<constraint name { <expressions> }>]
[enum { <name[=val],> }]
system
}
field REV_ID {
bits
8;
access ro;
reset h03;
}
block
block
register
register
field
field
field
field
memory
memory
register
register
regfile
register
field
field
register
field
register
register
302
RAL: Field Properties
RAL field can have any of the following specifications
bits
Number of bits in the field
access
See next slide
reset
Specify the hard reset value for the field
constraint
Constraint to be used when randomizing field
enum
Define symbolic name for field values
303
RAL: Field Access Types
RW
read-write
RO
read-only
WO
write-only; read error
W1
write-once
WO1
write-once; read error
W0C/S/T
write a 0 to bitwise-clear/set/toggle matching bits
W1C/S/T
write a 1 to bitwise-clear/set/toggle matching bits
RC/S
read clear /set all bits
WC/S
write clear /set all bits
WOC/S
write-only clear/set matching bits; read error
WRC/S
read clear/set all bits
WSRC [WCRS]
write sets all bits; read clears all bits [inverse]
W1SRC [W1CRS]
write one set matching bits; read clears all bits [inverse]
W0SRC [W0CRS]
write zero set matching bits; read clears all bits [inverse]
304
RAL File Register Syntax
n
Register
l
Contains fields
register reg_name {
[bytes n;]
[left_to_right;]
[<field name[=rename] [[n]] [@bit_offset[+incr]];>]
[<field name[[n]] [(hdl_path)] [@bit_offset] {<properties>}>]
[<constraint name {<expression>}>]
[shared [(hdl_path)];]
system
[doc {<text>}]
}
block
register HOST_ID {
field REV_ID;
field CHIP_ID { ... }
}
block
register
register
field
field
field
field
memory
memory
register
register
regfile
register
field
field
register
field
register
register
305
RAL: Register Properties
RAL registers can have any of the following specifications
bytes
Number of bytes in the register
left_to_right
If specified, fields are concatenated starting from
the most significant side of the register but justified
to the least-significant side
[n]
Array of fields
bit_offset
Bit offset from the least-significant bit
incr
Array offset bit increment
hdl_path
Specify the module instance containing the register
(backdoor access)
constraint
Constraint to be used when randomizing register
shared
All blocks instancing this register share the space
306
RAL File Register FILE Syntax
n
Register File
l
Contains register(s)
regfile regfile_name {
[<register name[=rename][[n]][(hdl_path)][@offset];>]
[<register name[[n]] [(hdl_path)] [@offset]
{<property>}]
[<constraint name {<expression>}>]
[shared [(hdl_path)];]
system
[doc {<text>}]
}
block
block
regfile REG_FILE {
register
memory
register
memory
register HOST_REG {
field
field
field
field
field USER_REG {
bits 16;
register
register
regfile
register
access rw;
field
field
register
reset h00;
field
register
register
}}}
307
RAL: Register File Properties
RAL register file can have any of the following specifications
[n]
Array of registers
hdl_path
Specify the module instance containing the register
(backdoor access)
offset
Address offset within the register file
shared
All blocks instancing this register share the space
308
RAL File Memory Syntax
n
Memory
l
Leaf level component
memory mem_name {
size m[k|M|G];
bits n;
[access rw|ro;]
[initial x|0|1|addr|literal[++|--];]
[shared [(hdl_path)];]
system
[doc {<text>}]
block
}
block
memory RAM {
size
4k;
bits
16;
access rw;
}
register
register
field
field
field
field
memory
memory
register
register
regfile
register
field
field
register
field
register
register
309
RAL: Memory Properties
RAL memories can have any of the following specifications
size
Number of consecutive addresses
bits
Number of bits in each address location
access
Allowed access type
noise
Non destructive access type
initial
Initial content of the memory
310
RAL File Block Syntax
n
Blocks
l
l
l
Instantiated in system
The smallest functional unit that can be verified is a block
Can have domains specified for corresponding physical
interfaces (minimum of two if specified)
block blk_name {
<proptery>
}
block blk_name {
domain name {
<property>
}
<domain name {
<property>
}
}
system
block
block
register
register
field
field
field
field
memory
memory
register
register
regfile
register
field
field
register
field
register
register
311
RAL File Block Syntax
n
Blocks
l
Contains register or memory elements
block blk_name {
bytes n;
[endian no|little|big|fifo_ls|fifo_ms;]
[<register name[=rename] [[n]][(hdl_path)] [@offset];>]
[<register name[[n]][(hdl_path)][@offset] {<property>}]
[<regfile name[=rename] [[n]] [(hdl_path)] [@offset] [+incr];>]
[<regfile name[[n]][(hdl_path)][@offset] [+incr] {<property>}]
[<memory name[=rename] [(hdl_path)] [@offset];>]
[<memory name [(hdl_path)] [@offset] {<property>}>]
[<constraint name {<expression>}>]
[doc {<text>}] block host_regmodel {
}
bytes 2;
register HOST_ID
(host_id)
@h0000;
register PORT_LOCK
(lock)
@h0100;
register HOST_REG[256] (host_reg[%d])
Must add
@h1000;
312
index
RAL: Block Properties
RAL block can have any of the following specifications
bytes
Number of bytes concurrently addressed
endian
Specifies hwo wide registers are mapped
313
RAL File System Syntax
n
Top Level or subsystem
l
Can have domains specified for corresponding physical
interfaces (minimum of two if specified)
system sys_name {
<proptery>
}
system
system sys_name {
domain name {
<property>
}
<domain name {
<property>
}
}
block
block
register
register
field
field
field
field
memory
memory
register
register
regfile
register
field
field
register
field
register
register
314
RAL File System Syntax
n
Top Level or subsystem
l
Contains other systems or blocks
system sys_name {
bytes n;
[endian no|little|big|fifo_ls|fifo_ms;]
[<block name[[.domain]=rename][[n]][(hdl_path)]@offset[+incr];>]
[<block name[[n]] [(hdl_path)] @offset [+incr] {<property>}>]
[<system name[[.domain]=rename][[n]][(hdl_path)]@offset[+incr];>]
[<system name[[n]][(hdl_path)] @offset [+incr] {<property>}]
[<constraint name {<expression>}>]
[doc {<text>}]
}
system dut_regmodel {
bytes 2;
block host_regmodel=HOST0 @'h0000;
block host_regmodel=HOST1 @'h8000;
}
315
Step 3: Use ralgen to Create RAL Model
ralgen uvm t dut_regmodel [Link]
// [Link]
register HOST_ID {
field REV_ID {}
field CHIP_ID {}
}
register PORT_LOCK {
field LOCK {}
}
register HOST_REG {
field USER_REG {}
}
memory RAM {}
block
host_regmodel {}
[Link]
system dut_regmodel {}
// ral_dut_regmodel.sv
class ral_reg_HOST_ID extends uvm_reg;
UVM
uvm_reg_field REV_ID;
RAL
uvm_reg_field CHIP_ID;
Classes
...
endclass : ral_reg_HOST_ID
class ral_reg_PORT_LOCK extends uvm_reg;
class ral_reg_HOST_REG extends uvm_reg;
class ral_mem_RAM extends uvm_mem;
class ral_block_host_regmodel extends uvm_reg_block;
rand ral_reg_HOST_ID
HOST_ID;
rand ral_reg_PORT_LOCK PORT_LOCK;
rand ral_reg_HOST_REG HOST_REG[256];
rand ral_mem_RAM
RAM;
...
endclass : ral_block_host_regmodel
class ral_sys_dut_regmodel extends uvm_reg_block;
rand ral_block_host_regmodel HOST0;
rand ral_block_host_regmodel HOST1;
...
endclass : ral_sys_dut_regmodel
316
UVM Sequence Using RAL
class host_bfm_sequence extends uvm_sequence#(host_data);
// utils macro and constructor
virtual task body();
if (starting_phase != null) starting_phase.raise_objection(this);
`uvm_do_with(req, {addr==h000; kind==host_data::READ;});
`uvm_do_with(req, {addr==h100; data==1; kind==host_data::WRITE;});
if (starting_phase != null) starting_phase.drop_objection(this);
endtask
endclass
Becomes
class host_ral_sequence extends uvm_reg_sequence;
ral_sys_dut_regmodel regmodel;
// utils macro and constructor
virtual task body();
if (starting_phase != null) starting_phase.raise_objection(this);
uvm_status_e
status;
uvm_reg_data_t data;
regmodel.HOST0.HOST_ID.read(status, data, UVM_FRONTDOOR,, this);
[Link](status, 1, UVM_FRONTDOOR,, this);
if (starting_phase != null) starting_phase.drop_objection(this);
endtask
endclass
317
Step 4: Create RAL Adapter
n
Environment needs a adapter to convert RAL
transactions to bus transactions
Sequencer
Unchanged
Adapter is required to
use existing test
structure
sequence
body()
Register model
Adapter
Ralgen
generated
classes
device
drivers
Driver Unchanged
Host Other
Port Ports
address
data
r_w
DUT
register
Memory
HOST_ID
LOCK
REG_FILE
Memory
318
RAL Adapter
class reg2host_adapter extends uvm_reg_adapter;
virtual function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
host_data tr;
tr = host_data::type_id::create("tr");
[Link] = ([Link] == UVM_READ) ? host_data::READ : host_data::WRITE;
[Link] = [Link];
[Link] = [Link];
return tr;
endfunction
virtual function void bus2reg(uvm_sequence_item bus_item,
ref uvm_reg_bus_op rw);
host_data tr;
if (!$cast(tr, bus_item))
`uvm_fatal("NOT_HOST_REG_TYPE", "bus_item is not correct type");
[Link] = ([Link] == host_data::READ) ? UVM_READ : UVM_WRITE;
[Link] = [Link];
[Link] = [Link];
sequence
[Link] = UVM_IS_OK;
body()
Register model
endfunction
endclass
reg2bus
Adapter
bus2reg
319
Step 5: Instantiate RAL model in environment
class host_env extends uvm_env;
host_agent
h_agent;
ral_sys_dut_regmodel regmodel;
string
hdl_path;
// utils macro and constructor not shown
virtual function void build_phase(uvm_phase phase);
// super.build_phase and component construction not shown
if (!uvm_config_db #(string)::get(this, "", "hdl_path", hdl_path))
`uvm_warning("HOSTCFG", "HDL path is not set!");
if (regmodel == null) begin
regmodel = ral_sys_dut_regmodel::type_id::create("regmodel", this);
[Link]();
regmodel.set_hdl_path_root(hdl_path);
end
endfunction
// Continued on next slide
320
Connect RAL in Environment
virtual function void connect_phase(uvm_phase phase);
reg2host_adapter reg2host;
reg2host = reg2host_adapter::type_id::create("reg2host", this);
drv.seq_item_port.connect(seqr.seq_item_export);
regmodel.default_map.set_sequencer(h_agent.seqr, reg2host);
endfunction
endclass
sequence
body()
Register model
Adapter
device
drivers
321
Step 6: RAL Test
class test_base extends uvm_test;
host_env
h_env;
// utils macro, constructor and other environments not shown
virtual function void build_phase(uvm_phase phase);
// super.build_phase and component construction not shown
uvm_config_db#(string)::set(this, "h_env", "hdl_path",
"router_test_top.dut");
endfunction
virtual task configure_phase(uvm_phase phase);
host_ral_sequence host_seq;
super.configure_phase(phase);
host_seq = host_ral_sequence::type_id::create("host_seq");
host_seq.regmodel = h_env.regmodel;
host_seq.start(null);
endtask
endclass
322
Built-in Test Implementation
n
Instantiate built-in test to do self-tests
class hw_reset_test extends test_base;
reset_sequence
reset_seq;
Built-in test
uvm_reg_hw_reset_seq reset_test;
instance
// utils macro and constructor left off
virtual task run_phase(uvm_phase phase);
phase.raise_objection(this, "Starting register tests");
// user reset sequence is required for uvm_reg_hw_reset_seq test
reset_seq = reset_sequence::type_id::create("reset_seq", this);
env.reset_seqr.execute_item(reset_seq);
Create and run
test
reset_test = uvm_reg_hw_reset_seq::type_id::create("reset_test", this);
reset_test.model = [Link];
reset_test.model.set_auto_predict(1);
reset_test.start(null);
phase.drop_objection(this, "Done with register tests");
endtask
endclass
simv +UVM_TESTNAME=hw_reset_test
323
Unit Objectives Review
Having completed this unit, you should be able to:
n
Create ralf file to represent DUT registers
Use ralgen to create UVM register classes
Use UVM register in sequences
Implement adapter to correctly pass UVM register
object to drivers
Run built-in UVM register tests
324
Appendix
UVM RAL Register Modes
UVM RAL Built-In Tests
UVM RAL Coverage
UVM RAL Shared Registers
325
UVM RAL Register Modes
326
UVM RAL Register Modes
n
Frontdoor read/write
Mirror
Desired
Backdoor read/write
Mirror set/get/update
reg
...
reg
Mirrored
reg
...
reg
sequencer
driver
DUT
reg
run
sequence
body()
run
device
drivers
...
reg
327
Frontdoor Write
n
[Link](.value(data), .path(UVM_FRONTDOOR));
l
l
l
l
Sequence creates WRITE transaction with value
Sequencer passes transaction to driver via TLM port
Driver calls device drivers to set value
Mirror
Desired
Mirror content is updated with value
reg
if auto predict is set in map
regmodel.default_map.set_auto_predict(1);
...
reg
Mirrored
reg
...
reg
sequencer
driver
DUT
reg
run
sequence
body()
run
device
drivers
...
reg
328
Frontdoor Read
n
[Link](.value(data), .path(UVM_FRONTDOOR));
l
l
l
l
Sequence creates READ transaction with value
Sequencer passes transaction to driver via TLM port
Driver calls device drivers to read value
Mirror
Desired
Mirror content is updated with value
reg
if auto predict is set in map
regmodel.default_map.set_auto_predict(1);
...
reg
Mirrored
reg
...
reg
sequencer
driver
DUT
reg
run
sequence
body()
run
device
drivers
...
reg
329
Backdoor Write
n
[Link](.value(data) , .path(UVM_BACKDOOR));
l
l
Write method set value in DUT via XMR
Mirror content is updated with value
if auto predict is set in map
Mirror
Desired
regmodel.default_map.set_auto_predict(1);
reg
...
reg
Mirrored
reg
...
reg
sequencer
driver
DUT
reg
run
sequence
body()
run
device
drivers
...
reg
330
Backdoor Read
n
[Link](.value(data) , .path(UVM_BACKDOOR));
l
l
Read method get value from DUT via XMR
Mirror content is updated with value
if auto predict is set in map
regmodel.default_map.set_auto_predict(1);
Mirror
Desired
reg
...
reg
Mirrored
reg
...
reg
sequencer
driver
DUT
reg
run
sequence
body()
run
device
drivers
...
reg
331
Mirror Read
n
data = [Link]();
l
Get value from desired mirror
Mirror
Desired
reg
...
reg
Mirrored
reg
...
reg
sequencer
driver
DUT
reg
run
sequence
body()
run
device
drivers
...
reg
332
Mirror Write
n
[Link](.value(data));
l
Set method set value in desired mirror
Mirror
Desired
reg
...
reg
Mirrored
reg
...
reg
sequencer
driver
DUT
reg
run
sequence
body()
run
device
drivers
...
reg
333
Mirror Value Creation
n
[Link]();
l
Populate desired mirror with random value
Mirror
Desired
reg
...
reg
Mirrored
reg
...
reg
sequencer
driver
DUT
reg
run
sequence
body()
run
device
drivers
...
reg
334
Mirrored & DUT Value Update
n
[Link]();
l
Update DUT and mirrored values with desired mirror
value if mirrored value is different from desired value
Mirror
Desired
reg
...
reg
Mirrored
reg
...
reg
sequencer
driver
DUT
reg
run
sequence
body()
run
device
drivers
...
reg
335
Mirrored & Desired Value Update
n
[Link]();
l
Update mirrored and desired values with DUT register
content
Mirror
Desired
reg
...
reg
Mirrored
reg
...
reg
sequencer
driver
DUT
reg
run
sequence
body()
run
device
drivers
...
reg
336
UVM RAL Built-In Tests
337
UVM RAL Test Sequences
n
Some of these test sequences depend on mirror to
be updated when backdoor is used to access DUT
registers
You should set auto predict in test
regmodel.default_map.set_auto_predict(1);
Sequence Name
Description
uvm_reg_hw_reset_seq
Test the hard reset values of register
uvm_reg_bit_bash_seq
Bit bash all bits of registers
uvm_reg_access_seq
Verify accessibility of all registers
uvm_mem_walk_seq
Verify memory with walking ones algorithm
uvm_mem_access_seq
Verify access by using front and back door
uvm_reg_mem_built_in_seq
Run all reg and memory tests
uvm_reg_mem_hdl_paths_seq
Verify hdl_path for reg and memory
uvm_reg_mem_shared_access_seq Verify accessibility of shared reg and memory
338
Agenda: Day 3
DAY
3
Sequence Library/Virtual Sequencer
10
More on Phasing
11
Register Abstraction Layer
12
Summary
339
Key Elements of UVM
n
Methodology
Scalable architecture
Standardized component communication
Customizable component phase execution
Flexible components configuration
Reusable register abstraction
340
UVM Methodology Guiding Principles
n
Top-down implementation methodology
l
Maximize design quality
l
l
l
Emphasizes Coverage Driven Verification
More testcases
More checks
Less code
Constrainable
Random Generation
Approaches
l
Reuse
Across tests
u Across blocks
u Across systems
u Across projects
u
l
l
Add
constraints
Directed
Testcase
Minimal Code
Modifications
Many runs,
different seeds
Functional
Coverage
Identify
holes
One verification environment, many tests
Minimize test-specific code
341
Scalable Architecture
n
Interface based agent enables block to system reuse
Top Level Harness
Test
Environment
Scoreboard
Master Agent
Passive
A
g
e
n
t
Sequencer
Driver
Bus
Monitor
DUTA
Slave Agent
Coverage
Sequencer
Scoreboard
Bus
Monitor
Bus
Monitor
Driver
DUTB
342
Standardized Component Communication
n
n
TLM 1.0 built into the base class
TLM 2.0 for cross language support
Top Level Harness
test
env
Scoreboard/
coverage
master agent
slave agent
sequencer
sequencer
default_sequence
default_sequence
driver
monitor
monitor
driver
DUTA
343
Customizable Component Phase Execution
n
Component phases are synchronized
l
l
Ensures correctly organized configuration and execution
Can be customized
component A
component B
component C
reset
reset
reset
main
time
configure
configure
main
main
shutdown
shutdown
344
Flexible Components Configuration (1/3)
n
uvm_config_db#(_type)::get(...)
class driver extends ; // simplified code
virtual router_io sigs;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(virtual router_io)::get(this, "",
"router_io", sigs))
`uvm_fatal("CFGERR", "Driver DUT interface not set");
endfunction
endclass
uvm_config_db#(_type)::set(...)
class test_base extends ; // simplified code
function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db#(virtual router_io)::set(this, "env.*",
"router_io", router_test_top.sigs);
endfunction
endclass
345
Flexible Components Configuration (2/3)
n
Sequence execution phase can be specified
class reset_sequence extends uvm_sequence; // simplified code
task body();
if (starting_phase != null)
starting_phase.raise_objection(this);
reset_dut();
if (starting_phase != null)
starting_phase.drop_objection(this);
endtask
endclass
uvm_config_db#(_type)::set(...) executes
sequence in chosen phase
class router_env extends uvm_env; // simplified code
function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db#(uvm_object_wrapper)::set(this, "seqr.reset_phase",
"default_sequence", reset_sequence::type_id::get());
endfunction
endclass
346
Flexible Components Configuration (3/3)
class test_new extends test_base; ...
`uvm_component_utils(test_new)
Replace
function void build_phase(uvm_phase);
component
super.build_phase(phase);
set_inst_override("[Link]", "component", "new_comp");
endfunction
endclass
class environment extends uvm_env;
...
function void build_phase(uvm_phase phase);
super.build_phase(phase);
comp = component::type_id::create("comp", this);
endfunction
use create() to build
endclass
simv
uvm_top
run_test()
uvm_test_top
uvm_test_top
component
class new_comp extends component;
`uvm_component_utils(new_comp)
function new(string name, uvm_component parent);
virtual task component_task();
// modified component functionality
endtask
Modify
endclass
operation
env
env
comp
new_comp
comp
347
Standardized Register Abstraction
sequence
Physical addresses
are abstracted away
body()
Register model
Translator
Sequences does not
need modification
throughout block to
system integration
device
drivers
Host Other
Port Ports
address
data
r_w
DUT
register
Memory
HOST_ID
LOCK
REG_FILE
Memory
class host_ral_sequence extends uvm_reg_sequence;
virtual task body(); ...
regmodel.HOST0.HOST_ID.read(status, data, UVM_FRONTDOOR,, this);
[Link](status, 1, UVM_FRONTDOOR,, this);
endtask
endclass
348
Getting Help
n
UVM class reference guide:
l
Code examples:
l
vcs_support@[Link]
SNUG (Synopsys Users Group):
l
[Link]
VCS support:
l
$VCS_HOME/doc/examples/uvm_1.0
Solvnet:
l
$VCS_HOME/doc/UserGuide/pdf/UVM_Class_Reference_Manual_1.[Link]
[Link]
Accellera web site:
l
l
[Link]
Check for source code
349
Lab 7 Introduction
Implement RAL
60 min
Implement
register sequence
without RAL
Compile and
Simulate
Create RAL
representation
Create register
sequence with RAL
Compile and
Simulate
350
Thats all Folks!
351
352