3. Cadence Confidential
Workshop Setup Instructions
This workshop uses the following environment variables that you must ensure are set.
• SOCV_KIT_HOME - Points to the install location of the kit and is used to refer to examples
contained inside the kit. It is used by both the full SoC Verification Kit and the reduced version
known as the IP Kit. The following illustrates how it should be set:
% setenv SOCV_KIT_HOME <INCISIV _install_dir>/kits/VerificationKit
• MY_WORK_AREA - Points to general purpose working directory that the user is required to
create. This is where all the workshop labs should be run from and kit navigator launched. The
user is free to have this work area located where ever they want. An example suggestion is:
% mkdir <path_to_local_work_area>/work
% setenv MY_WORK_AREA <path_to_local_work_area>/work
• MY_REGRESSION_AREA - Points to the directory Incisive Manager stores its regression
content into and must be created by the user. This folder can and should be cleaned periodically.
It is used to retain regression data between runs. This directory can be located anywhere but an
example suggestion is:
% mkdir $MY_WORK_AREA/sessions
% setenv MY_REGRESSION_AREA $MY_WORK_AREA/sessions
After setting up the environment variables type:
% source $SOCV_KIT_HOME/env.csh
3
4. Cadence Confidential
The UVM Register Layer Classes (uvm_reg)
• This module has two objectives:
– Introduction to the UVM Register Layer Classes (uvm_reg)
– Teaching how to integrate and use uvm_reg by incorporating it
in a simple verification environment (UART design)
4
5. Cadence Confidential
Agenda
• Why Model Registers?
• Terminology
• Using uvm_reg to verify a DUT
– Capture DUT register attributes
– Connecting the uvm_reg components in a testbench
– Control register scenarios
– Use uvm_reg for checking and coverage
• Summary
5
6. Cadence Confidential
SW Application
SW Device Drivers
From Keyboard To screen From barcode /
credit card reader
To / From
credit center
6
Typical System-Level Environment
SoC
(DUT)
Bridge
CPU DMA
USB
Memory
Ethernet
XCore XCore
CPU Bus (AHB)
Peripheral Bus (Xbus)
Each peripheral contains
registers which are mapped
to the CPU’s address space.
The CPU controls the entire
system, by reading and
writing device registers
Many devices are attached to a bus
and have a register set that interfaces
between the DUT and a programmer’s
model
7. Cadence Confidential
7
UVM Register Layer Classes: Motivation
• Almost all devices have registers
– Hundreds (even thousands) of registers is not uncommon
• In verifying a device (DUT), one needs to control,
observe and check register behavior
– Randomize the device configuration and determine initial
register values
– Execute transactions to write/read registers and memory blocks
– Read and write registers as part of run-time normal operation
and send traffic on external interfaces in parallel.
– Check the device by comparing registers and memory values to
a reference (shadow) model
– Collect coverage of device modes
Much of the device control and coverage is
done at the register level
8. Cadence Confidential
DUT
XCore
8
Verifying a Component of the DUT (XCore)
CPU Bus Interface
Peripheral Interface
SoC
(DUT)
Bridge
CPU DMA
USB
Memory
Ethernet
XCore XCore
CPU Bus (AHB)
Peripheral Bus (Xbus)
9. Cadence Confidential
Configuring Devices Using uvm_reg
9
dut
APB
master
agent
driver
seqr
memctl
mode0
mode2
mode1
mode3
status
mem_inst
memory
32x4096
Register Model
Register Block
0x1000 mode0
mode1
mode2
mode3
status
0x0000
0x0FFF
memory
(4K)
0x1001
0x1002
0x1003
0x1010
.
.
.
apb_if
mon
Register model shadows the
registers, register blocks and
memories in the DUT
Register sequence executes
register operations
Randomize environment
and DUT configuration
Master UVC drives
bus transactions
Register
Sequence
Adapter converts
register operations to
bus transactions
Adapter
9
10. Cadence Confidential
Register Monitoring and Checking
10
dut
APB
master
agent
driver
seqr
memctl
mode0
mode2
mode1
mode3
status
mem_inst
memory
32x4096
Register Model
Register Block
0x1000 mode0
mode1
mode2
mode3
status
0x0000
0x0FFF
memory
(4K)
0x1001
0x1002
0x1003
0x1010
.
.
.
apb_if
mon
Adapter converts bus
transactions back to
register operations
A bus monitor captures
transactions on the bus
and sends them via TLM
Functional coverage
is sampled in the
register model
Adapter
Register model (database) contains
address map(s) and is placed in the
testbench. Also holds attributes
and expected values.
Predictor receives transactions:
Predictor
Component
Clear separation
of injection and
collection path is
key!
Predictor:
Write: update the model
Read: compare (and update)
the register model
10
11. Cadence Confidential
12
Testbench
Module UVC
Register Model instantiation and hook-up
dut
APB
master
driver coll
seqr
memctl
mode0
mode2
mode1
mode3
Adapter
object
Virtual
Sequencer
Register Model
Register Block
0x1000 mode0
mode1
mode2
mode3
Implement adapter
bus2reg and reg2bus
tasks
Place register model, adapter,
module UVC and register
sequencer in the testbench.
Predictor
Component
status
mem_inst
memory
32x4096
status
0x0000
0x0FFF
memory
(4K)
0x1001
0x1002
0x1003
0x1010
.
.
.
apb_if
mon
Register
Sequencer
Add the predictor component
to the module UVC
12. Cadence Confidential
13
Registers and Register Operations
Register Operation
uvm_reg_bus_op: register operation
addr: sized integer
kind: READ, WRITE
data: the register variable
status: result of transaction
Register
name: rx_status_reg
fields: error: 1’b1 // flag
error_cnt: 7’h04
register_sequencer uvm_reg_bus_op:
addr: ’h03
kind: READ
data: ‘h84
xcore_sequencer transaction:
xaddr: ’h03
xdata: ‘h84
xwr_rd: READ
tx_mode
rx_mode
tx_status
rx_status
Reg-file
0x00
0x02
0x01
0x03
e
7 0
6
error_count
Register: Status Reg
13. Cadence Confidential
• A SystemVerilog register and memory package
• Included in the 1.1 library
• Jointly produced by
• SNPS RAL API was chosen as the starting baseline for this new
feature
• Accellera committee modified the API to be consistent with UVM
• The use model is enhanced with extensions from uvm_rgm:
– Configuration sequences
– Passive monitoring
• This presentation includes:
– API modifications for ovm_rgm and uvm_rgm users that wish to migrate
to uvm_reg
– Information for VMM RAL users incorporating the new use model
UVM_REG
Objective: Encourage correct use-model of uvm_reg
to maximize automation and reuse
14
14. Cadence Confidential
• Models registers and memories in the design
• Architecture is hierarchical
– Blocks can contain sub-blocks / registers / memories
• Supports all ipXact1.5 access policies
– No built-in generator support
• Supports virtual registers
• Provides an API for accessing the model and generating stimulus
• Write / read / update / mirror / peek / poke / get / set etc
• Both front-door and back-door access possible
– Multiple backdoor paths for registers / fields
• Built-in-sequences
• Using maps, same object can be targeted to various sequencers
• Field level access support
• Checking and coverage are also available
• Objects can be extended using regular UVM extensions
• Call-back support
UVM_REG Features
15
15. Cadence Confidential
• IP-XACT is the Accellera XML standard format to capture the
register model (driven by the IPXACT sub-committee)
• Proprietary input formats can be used with caution
Capturing UVM_REG Model
Following the IP-XACT Hierarchy
IP-XACT
Register
Generator
Utility Reg classes
and DB
Generated SV code is
vendor specific
UVM config
sequences
testbench
Placed inside a testbench
for randomizing, checking,
and coverage
Provided by Vendors
UVM_reg
base classes
Users capture their project
Register model in IPXACT
User manually creates reusable
UVM configuration sequences
16
16. Cadence Confidential
Cadence IP-XACT Generator (example)
$IREG_GEN/bin/ireggen –i ipxact_example.xml –d ./out –qt
17
<++> Cadence iregGen version 1.03
<++> XML parsed. Started decoding
......
<++> Decoding done
<++> Input File: ./ipxact_example.xml
<++> Number of AddrMaps = 1
<++> Number of RegFiles = 1
<++> Number of Registers = 6
<++> Number of Memories = 0
<++> Files Created : ./rdb.sv
<++> Files Created : ./quickTest.sv
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
To simlulate using INCISIVE:
irun -clean -uvmhome $UVM_HOME
+incdir+.
./quickTest.sv
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
Command
Output
Cadence generator options:
-i (input file name)
-d (directory for output files)
-qt (creates a simple test)
17. Cadence Confidential
18
Why is IES the Best Platform for UVM_REG?
• Technology
– According to users, IES Simulator demonstrated significantly
more scalability than other simulators
– Cadence IPXACT Generator
• Supports both the UVM_RGM and the UVM_REG packages (via a
switch)
• IPXACT front-end is proven in many projects
• Supports capabilities that are not yet in the standard library
• Results are tuned for performance and scalability
• Includes IPXACT extensions for effective register verification
• Knowledge and expertise
– Cadence field team and services are familiar with the
UVM_REG new methodology and use model
18. Cadence Confidential
Agenda
• Why Model Registers?
• Terminology
• Using uvm_reg to verify a DUT
– Capture DUT register attributes
– Connecting the uvm_reg components in a testbench
– Control register scenarios
– Use uvm_reg for checking and coverage
• Summary
19
19. Cadence Confidential
• All objects extend from uvm_object
– Allows use of UVM automation features!
• Each field is instance of uvm_reg_field
– Fields have many attributes such as reset value, and access
mode
– Holds three copies of the value:
• Mirrored: What we think is in the HW
• Value: A value to be randomized
• Desired: A desired value for the field
• Registers extend from uvm_reg class
– An abstract representation of a DUT register kind
– Contains one or more fields
– Register width set in constructor
– Doesn’t need to have an associated address
UVM_REG Building Blocks
class config_reg extends uvm_reg;
uvm_reg_field f1; // 1-bit
uvm_reg_field f2; // 1-bit
uvm_reg_field f3; // 4-bits
uvm_reg_field f4; // 2-bits
endclass : config_reg
f1
f2
f3
f4
config_reg
20
20. Cadence Confidential
Field Access Policies Supported
RO Read-Only
RW Read-Write
RC Read-only, Clear-on-read
RS Set-on-read (all bits become
‘1’ on read)
WRC Writeable, clear-on-read
WRS Writable, Sets-on-read
WC Clear-on-write
WS Set-on-write
WSRC Set-on-write, clear-on-read
WCRS Clear-on-write, set-on-read
W1C Write ‘1’ to clear bits
W1S Write ‘1’ to set bits
W1T Write ‘1’ to toggle bits
W0C Write ‘0’ to clear bits
W0S Write ‘0’ to set bits
W0T Write ‘0’ to toggle bits
W1SRC Write ‘1’ to set and clear-on-read
W1CRS Write ‘1’ to clear and set-on-read
W0SRC Write ‘0’ to set and clear-on-read
W0CRS Write ‘0’ to clear and set-on-read
WO Write-only
WOC When written sets the field to ‘0’.
Read undeterministic
WOS When written sets all bits to ‘1’.
Read undeterministic
W1 Write-once. Next time onwards,
write is ignored. Read returns
the value
WO1 Write-once. Next time onwards,
write is ignored. Read is
undeterministic
DC RW but no check
21
21. Cadence Confidential
• A register file extends uvm_reg_file
– Contains multiple register
definitions
– Each register is offset from a
common address
– Useful for reuse at higher
levels of abstraction
• A memory is an instance of uvm_mem
– All elements are of the same width
– Memory width / depth set in constructor
UVM_REG Building Blocks (Continued)
count
0x10
i0
i1
i2
i3
0x0C
0x08
f1
f2
f3
f4
0x04
ch0
ch1
ch2
ch3
rsvd
Register File
error_cnt
interrupt
status
config
memory
8x256
0x00
0x01
0x02
.
.
0xFF
22
22. Cadence Confidential
0xffff
Blocks and Maps
• Block (Register Model)
– Extends from uvm_reg_block class
– A quasi-static UVM component represents a
“shadow” model of registers/memories in
the system address space
– Blocks can be nested
– Every block has at least one map
• Map
– Extends from uvm_reg_map class
– Holds the information required to drive
objects through various sequencer/driver
pairs
– Address maps can be nested
Sub-Block
Config
Status
Interrupt
Error Cnt
0x014
0x018
0x01C
0x020
Memory
8x256
0x800
0x8ff
0x1000
0x1004
0x11ff
Register Model
0x0000
...
...
...
...
Reg
File
23
23. Cadence Confidential
UVM_REG Class Diagram
uvm_reg_field
my_reg
uvm_reg
1..N
uvm_mem_mam
uvm_mem
uvm_reg_file
my_regfile
1..N
1..N
1..N
uvm_reg_block
uvm_reg_map
my_block
1..N
1..N
1..N
uvm_* UVM base class
my_* User-defined class
Registers are composed
of one or more fields
For scalability, no unique
class per field
Map all the registers for a
bus interface
Register files comprise
one or more registers
Memories have common
data width/format and
sequential addresses
This is your register
model and can contain
sub-blocks
24
24. Cadence Confidential
class config_reg_c extends uvm_reg;
rand uvm_reg_field f1;
rand uvm_reg_field f2;
rand uvm_reg_field f3;
rand uvm_reg_field f4;
virtual function void build();
f1 = uvm_reg_field::type_id::create(“f1");
f1.configure(this, 1, 0, "RW", 0, ‘h0, 1, 1, 1);
f2= uvm_reg_field::type_id::create("f2");
f2.configure(this, 1, 1, "RO", 0, ‘h0, 1, 1, 1);
f3 = uvm_reg_field::type_id::create(“f3");
f3.configure(this, 4, 2, "RW", 0, ‘h0, 1, 1, 1);
f4= uvm_reg_field::type_id::create("f4");
f4.configure(this, 2, 6, “WO", 0, ‘h0, 1, 1, 1);
endfunction
`uvm_register_cb(config_reg_c, uvm_reg_cbs)
`uvm_set_super_type(config_reg, uvm_reg)
`uvm_object_utils(config_reg_c)
function new (input string name="config_reg_c");
super.new(name, 8, UVM_NO_COVERAGE);
endfunction : new
endclass : config_reg_c
UVM_REG fields
Hard Reset
Reg Width
Offset
Register Declaration Generated by iregGen
Typically does not need to be read by users
Callback + derivation support
Size
config_reg
0
2
6
7
f1
f2
f3
f4
In the build() method, each field
is created, and then configured
Enables randomization of the field
25
26. Cadence Confidential
class memctl_rf_c extends uvm_reg_block;
rand mode_reg_c mode_reg;
rand config_reg_c config_reg;
virtual function void build();
// create and configure each register
// specify address offset and hdl_path for backdoor access
endfunction
// constructor and uvm_object_utils
endclass : memctl_rf_c
class memctl_model_c extends uvm_reg_block;
rand memctl_rf_c memctl_rf;
rand memory256_c memory256;
virtual function void build();
// create and configure the register file and memory
// specify hdl_path for backdoor access
endfunction
// constructor and uvm_object_utils
endclass : memctl_model_c
Register file, memory
(can also contain fields)
Register File and Register Model
Generated by the iregGen script
27
Registers (can also
contain fields)
The register model, memctl_model_c,
is placed in the testbench and configured
27. Cadence Confidential
Register Operations
• Operations that access registers
• Includes attributes:
– addr: Register access via actual address in the address map
• Access can be via name or address
– kind: Read or write operation
– data: The register variable which includes value of its fields,
uvm_reg_bus_op:
addr: sized integer
kind: READ, WRITE
data: the register variable
status: result of transaction
28
28. Cadence Confidential
Access APIs for memories / registers / field
• write()/read(): Write/read immediate value to DUT.
• set()/get() : Sets or gets the desired-register’s value.
• randomize() : Using the randomize() method copies the
randomized value in the uvm_reg_field::value property into the
desired value of the mirror by the post_randomize() method.
• update() : Invokes the write() method if the desired value
(previously modified using set() or randomize()) is different from
the mirrored value.
• mirror() : Invokes the read() method to update the
mirrored value based on the readback value. mirror() can also
compare the readback value with the current mirrored value
before updating it.
29
* Update and mirror API can be called on container (block) too
29. Cadence Confidential
Register sequencer and sequences
• Register sequencer is an UVM
sequencer
• Its sequence item is a
uvm_reg_bus_op
– And not a sequence of registers
– The operation itself is protocol-
neutral
Register sequencer
Register
Fields
Attributes
Register operation sequences
Operation to perform
on a specific register
The register to be
accessed
uvm_reg_bus_op
addr
kind
data
30
class memctl_reg_sequencer extends uvm_sequencer;
`uvm_component_utils(memctl_reg_sequencer)
// Contains a pointer to the register model
memctl_reg_model_c reg_model;
function new( string name, uvm_component parent);
super.new(name, parent);
endfunction
endclass : memctl_reg_sequencer
A reference to the register
model for reg sequences
30. Cadence Confidential
Creating Register Sequences
class blk_seq extends uvm_reg_sequence;
my_regfile model;
`uvm_object_utils(blk_seq)
function new ( string name=“blk_seq“ );
super.new(name);
endfunction : new
virtual task body();
uvm_status_e status;
int data;
model.config.write(status, ‘h12, .parent(this));
model.config.write(status, ‘h34, UVM_BACKDOOR, .parent(this));
model.config.read(status, data, UVM_BACKDOOR, .parent(this));
model.my_mem.write(status, ‘h8, ‘h1234_5678, .parent(this));
void'(model.randomize());
model.update(status, UVM_BACKDOOR, .parent(this));
model.mirror(status, UVM_CHECK, UVM_BACKDOOR, .parent(this));
endtask : body
endclass : blk_seq
31
Frontdoor Write
Backdoor Write
Backdoor Read
Container level
Backdoor update
Container level
Backdoor mirror
Pointer to the register model container
Memory frontdoor
Note that there are read/write
tasks that cover the do items
31. Cadence Confidential
Agenda
• Why Model Registers?
• Terminology
• Using uvm_reg to verify a DUT
– Capture DUT register attributes
– Connecting the uvm_reg components in a testbench
– Control register scenarios
– Use uvm_reg for checking and coverage
• Summary
32
32. Cadence Confidential
Test 1
UVM Testbench
UART DUT and Verification Environment
Interface & white-box
coverage
Scoreboard
Multi-channel controller
Imitates external
device by
generating frames
Programs the
UART and
transfers traffic
APB
Verification
Component
Module Verification
Component
UART DUT (Verilog RTL)
APB
Interface
Mode
Switch
Control/Interrupt
Logic
Rx FIFO Receiver
Transmitter
Tx FIFO
Control/Status
Registers
txd
rxd
UART
Verification
Component
Controls APB and
UART components
Test 2 Test 3
Tests indicate which
stimulus sequences to
execute
APB
UART
Serial
33
33. Cadence Confidential
Steps for Integrating uvm_reg in UART Design
1. Capturing the register description in IP-XACT
2. Generating the SV model (registers, register file,
address map, register block)
3. Connecting the register database to the verification
environment
4. Creating register sequences
5. Checking register behavior
34
34. Cadence Confidential
Creating the Register Model
• uvm_reg uses IP-XACT standard input format to capture
register attributes
• Using this standard formats, we describe:
– Register files
– Register and fields
• Including various field attributes
• Vendor extensions are added to support additional
needs:
– Backdoor access, coverage, constraints, etc
• Corresponding UVM classes (SV code) are generated
and are used by the Testbench developer
35
35. Cadence Confidential
IP-XACT Input
• IP-XACT is a standard input XML format
• Users can use an XML editors to capture the needed
register model
– Eclipse – free
– SPI-Java
– Examples
• Our assumption is that many users will create scripts
that convert documents to IP-XACT format
36
36. Cadence Confidential
Creating the Register Database
• Describe the design registers using IP-XACT format
(spirit, xml)
– Describe fields of each register, reset values, compare masks,
update masks, constraints, coverage, access modes, etc
• Use the converter utility to generate SystemVerilog from
the xml/spirit format
– Register and Field definitions
– Register file(s) containing registers at specified addresses
– Register block – an UVM component to place in your testbench
37
38. Cadence Confidential
IP-XACT Format
<spirit:name>apb_uart_reg_db</spirit:name> <!–REGISTER DATABASE NAME -->
<spirit:memoryMap> <!– START OF ADDRESS MAP DEFINITION -->
<spirit:name>uart_addr_map</spirit:name>
<spirit:addressBlock> <!-- START OF REGISTER FILE -->
<spirit:name>uart_rf</spirit:name>
<spirit:baseAddress>0x00</spirit:baseAddress>
<spirit:range>32</spirit:range>
<spirit:width>32</spirit:width>
<spirit:register> <!– UART CONTROL REGISTER -->
<spirit:name>control_reg</spirit:name>
<spirit:addressOffset>0x00</spirit:addressOffset>
<spirit:size>32</spirit:size>
<spirit:access>read-write</spirit:access>
<spirit:field> <!-- FIELD -->
<spirit:name>rxrs</spirit:name>
<spirit:bitOffset>0</spirit:bitOffset>
<spirit:bitWidth>1</spirit:bitWidth>
</spirit:field>
. . .
39
39. Cadence Confidential
IP-XACT Format – Vendor Extensions
40
• The SPIRIT IP-XACT standard input format was
incomplete for users needs
– For example constraints, coverage, backdoor path etc’ had to be
introduced
– IP-XACT supports vendor extensions
<!-- FIELD VENDOR EXTENSIONS-->
<spirit:vendorExtensions>
<!-- collect_coverage: cov_all, cov_none, cov_update, cov_compare_and_update -->
<vendorExtensions:collect_coverage>cov_all</vendorExtensions:collect_coverage>
</spirit:vendorExtensions>
<!-- REGISTER VENDOR EXTENSIONS -->
<spirit:vendorExtensions>
<!-- type: Optional - default is register_name -->
<vendorExtensions:type>control_reg_c</vendorExtensions:type>
<!-- Constraint: with special characters (less-than, greater-than) -->
<vendorExtensions:constraint>c1 { rxen.value == !txen.value;}</vendorExtensions:constraint>
<vendorExtensions:constraint>rtx_c { cclk.value == 1’b1;}</vendorExtensions:constraint>
<!– soft reset value and mask: Optional - set to 0 by default -->
<vendorExtensions:soft_reset_value>0x0014</vendorExtensions:soft_reset_value>
<vendorExtensions:soft_reset_mask>0xFFFFFFFF</vendorExtensions:soft_reset_mask>
<!-- compare and update masks: Optional - determines fields updated/compared during checking
<vendorExtensions:compare_mask>0x0000FFFF</vendorExtensions:compare_mask>
<vendorExtensions:update_mask>0x000001D7</vendorExtensions:update_mask>
</spirit:vendorExtensions>
40. Cadence Confidential
Running the Converter
• The Cadence IP-XACT parser reads the XML code and generates
the SV classes for the register/field definitions, register file, address
map and register database
• To run the parser:
Note: run with –h to get the full list of options
• We do NOT recommended editing the generated code
– May need to re-generate when modifications are needed
– Use the factory to modify register definitions
41
$IREG_GEN/bin/iregGen –i ipxact_example.xml –d ./out –qt
41. Cadence Confidential
$IREG_GEN/bin/iregGen
-i <fileName> # Input ipxact (XML) file
# Optional Arguments to iregGen
-o <outputFile> # Output register data-base file name. Default ‘rdb.sv’
-d <outputDir> # Output directory where the generated files will be created
-ta <string> # Append class name with this string when <type> is not specified
-p <name> # All output files will get pre-pended with this name
-pkg <name> # A package with specified name will be created
-to <output kind> # Generate output code for ovm_rgm / uvm_rgm or uvm_reg (default)
-sp # User hook to dump individual addrBlock as separate file
-nfe # Flag to disable field enumerations
-nc # User hook to disable generation of register level functional coverage code
-cc # User hook to disable generation of container level functional coverage code
-ga # Flag for generating access file for backdoor access optimization
-sim <simCmd> # Simulator run command [default 'irun']
-qt # Creates stand-alone test that prints register dataBase, for quick sanity check
-test <fileName> # Creates stand-alone test with given name
iregGen : ipXact to System-Verilog generator
42
42. Cadence Confidential
class config_reg_c extends uvm_reg;
rand uvm_reg_field f1;
rand uvm_reg_field f2;
rand uvm_reg_field f3;
rand uvm_reg_field f4;
virtual function void build();
f1 = uvm_reg_field::type_id::create(“f1");
f1.configure(this, 1, 0, "RW", 0, ‘h0, 1, 1, 1);
f2= uvm_reg_field::type_id::create("f2");
f2.configure(this, 1, 1, "RO", 0, ‘h0, 1, 1, 1);
f3 = uvm_reg_field::type_id::create(“f3");
f3.configure(this, 4, 2, "RW", 0, ‘h0, 1, 1, 1);
f4= uvm_reg_field::type_id::create("f4");
f4.configure(this, 2, 6, “WO", 0, ‘h0, 1, 1, 1);
endfunction
`uvm_register_cb(config_reg_c, uvm_reg_cbs)
`uvm_set_super_type(config_reg_c, uvm_reg)
`uvm_object_utils(config_reg_c)
function new (input string name="config_reg_c");
super.new(name, 8, UVM_NO_COVERAGE);
endfunction : new
endclass : config_reg_c
UVM_REG fields
Hard Reset
Reg Width
Offset
Register Declaration Generated by iregGen
Typically does not need to be read by users
Callback + derivation support
Size
config_reg
0
2
6
7
f1
f2
f3
f4
In the build() method, each field
is created, and then configured
Enables randomization of the field
43
43. Cadence Confidential
class memctl_rf_c extends uvm_reg_block;
rand mode_reg_c mode_reg;
rand config_reg_c config_reg;
virtual function void build();
mode_reg = mode_reg_c::type_id::create(“mode_reg“, get_full_name());
config_reg = config_reg_c::type_id::create(“config_reg“, get_full_name());
mode_reg.configure(this, null, “mode_reg”);
mode_reg.build();
config_reg.configure(this, null, “config_reg”);
config_reg.build();
// define address mappings
default_map = create_map(“default_map”, 0, 1, UVM_LITTLE_ENDIAN);
default_map.add_reg(mode_reg, ‘h0, “RW”);
default_map.add_reg(config_reg, ‘h10, “RW”);
endfunction
`uvm_object_utils(memctl_rf_c)
function new (input string name=“memctl_rf_c");
super.new(name, UVM_NO_COVERAGE);
endfunction : new
endclass : memctl_rf_c
Registers (can also contain fields)
hdl_path for backdoor access
Address offset
Register File Declaration
Generated by the iregGen script
In the build() method, each register
is created, and then configured
A default map is created with
address offset information
44
44. Cadence Confidential
class memctl_reg_model_c extends uvm_reg_block;
rand memctl_rf_c memctl_rf;
rand memory256_c memory256;
virtual function void build();
// define address mappings
default_map = create_map(“default_map”, 0, 1, UVM_LITTLE_ENDIAN);
// REGISTER FILE
memctl_rf = memctl_rf_c::type_id::create(“memctl_rf“, , get_full_name());
memctl_rf.configure(this, “memctl”);
memctl_rf.build();
memctl_rf.lock_model();
default_map.add_submap(memctl_rf.default_map, ‘h1000”);
// MEMORY
memory256 = memory256_c::type_id::create(“memory256”);
memory256.configure(this, “mem_inst.memory”);
memory256.build();
default_map.add_mem(memory256, ‘h0000, “RW”);
set_hdl_path_root(“top.dut”);
this.lock_model();
endfunction
`uvm_object_utils(memctl_reg_model_c)
function new (input string name=“memctl_reg_model_c");
super.new(name, UVM_NO_COVERAGE);
endfunction : new
endclass : memctl_reg_model_c
Register file, memory
(can also contain fields)
hdl_path for backdoor access
Address offset for register file
Register Block Declaration (Register Model)
Generated by the iregGen script
hdl_path for backdoor access
Address offset for memory
Root hdl_path for register model
45
45. Cadence Confidential
Register (or container) Array
rand ureg_t ureg [0:1][1:10];
virtual function void build();
….
for ( int y=0; y<=1; y++ ) begin
for ( int x=1; x<=10; x++ ) begin
uvm_reg_addr_t laddr=((y*16)+(4*x));
ureg[x][y] = reg_table_b_type::type_id::create($psprintf(“ureg[%0d][%0d]", x, y));
ureg[x][y].build();
ureg[x][y].configure(this, null, $psprintf(“ureg[%0d][%0d]", x, y));
default_map.add_reg(ureg[x][y], laddr, "RW");
end
end
HDL path
Offset
46
46. Cadence Confidential
New Register Types : Indirect Registers
• Indirect registers are used when registers are not mapped
in the address map and can only be accessed indirectly
– Read/write operations are executed through mapped registers
– Address register – is like a normal register
– Data register – uses the above address register for address index
– Update/Compare uses indexed address/data
– get_all_regs() will get ALL registers, including indexed registers
47
0x03
0x04 addr_reg ‘h0002
0x05 data_reg ‘h3489
0x06
0x00
0x01
0x02 ‘h3489
0x03
Mapped Registers Indirect Registers
47. Cadence Confidential
Indirect Registers: IPXACT Code
48
<spirit:register> <!– INDIRECT DATA REGISTER-->
<spirit:name>ireg</spirit:name>
<spirit:addressOffset>0x5</spirit:addressOffset>
<spirit:size>16</spirit:size>
<spirit:access>read-write</spirit:access>
<spirit:vendorExtensions> <!-- REGISTER VENDOR EXTENSIONS -->
<vendorExtensions:type>ireg_c</vendorExtensions:type>
<vendorExtensions:indirect_addr_reg>addr_reg</vendorExtensions:indirect_addr
<vendorExtensions:array>
<vendorExtensions:x_from>1</vendorExtensions:x_from>
<vendorExtensions:x_to>4</vendorExtensions:x_to>
<vendorExtensions:offset_calc>'h0+x-1</vendorExtensions:offset_calc>
</vendorExtensions:array>
</spirit:vendorExtensions>
</spirit:register>
address register
offset value
Note: Indirect address
registers are declared
like normal registers
49. Cadence Confidential
New Register Types : Shared (Twin) Registers
• Sometimes a single address is used to access one
register when writing and another register when reading
– This is referred to as a shared or twin register
– Declare the registers as you normally would in IPXACT
• One register must be read-only, the other must be write-only
• Both registers specify the same address offset
– The parser will automatically recognize a shared register and add
code to the register database to support
50
DUT
rd_data_reg
wr_data_reg
reg_file
0x09 shr_ro_reg
0x09 shr_wo_reg Writes to addr:0x09
will update this register
Reads from addr:0x09
will return this reg value
50. Cadence Confidential
Shared Registers: SystemVerilog Code
51
// Defined with read-only access in IPXACT
class reg_RO extends uvm_reg;
`uvm_object_utils(reg_RO)
virtual function void build();
F1 = uvm_reg_field::type_id::create("F1");
F1.configure(this, 8, 0, "RO", 0, 8'h00, 1, 0, 1);
F2 = uvm_reg_field::type_id::create("F2");
F2.configure(this, 8, 16, "RC", 0, 8'hFF, 1, 0, 1);
endfunction: build
endclass : reg_RO
// Defined with write-only access in IPXACT
class reg_WO extends uvm_reg;
`uvm_object_utils(reg_WO)
virtual function void build();
F1 = uvm_reg_field::type_id::create("F1");
F1.configure(this, 8, 4, "WO", 0, 8'hAA, 1, 1, 1);
F2 = uvm_reg_field::type_id::create("F2");
F2.configure(this, 12, 12, "WO", 0, 12'hCCC, 1, 1, 1);
endfunction: build
endclass : reg_WO
Define shared register like normal
registers
52. Cadence Confidential
New Register Types : Aliased Register
• Occasionally a register (or register file) is mapped to
multiple addresses
– This is referred to as a aliased register (register file)
– Access to any of the aliased addresses will access all references
– Aliased register may have different behavior depending on
address
53
Note: Shared Register – Two registers accessed via the same address
Aliased Register – One register accessed via multiple addresses
53. Cadence Confidential
Aliased Register: SystemVerilog Code
54
class my_reg_Ra extends uvm_reg;
rand uvm_reg_field F1;
...
virtual function void build();
F1 = uvm_reg_field::type_id::create("F1");
F1.configure(this, 8, 0, "RW", 0, 8'h0, 1, 1, 1);
endfunction
...
endclass
class my_reg_Rb extends uvm_reg;
uvm_reg_field F1;
...
virtual function void build();
F1 = uvm_reg_field::type_id::create("F1");
F1.configure(this, 8, 0, "RO", 0, 8'h0, 1, 0, 1);
endfunction
2 Normal register
declaration
class my_blk extends uvm_reg_block;
rand my_reg_Ra Ra;
rand my_reg_Rb Rb;
virtual function build();
default_map = create_map("", 0, 4, UVM_BIG_ENDIAN);
Ra = reg_Ra::type_id::create("Ra",,get_full_name());
Ra.configure(this, null);
Ra.build();
Rb = reg_Rb::type_id::create("Rb",,get_full_name());
Rb.configure(this, null);
Rb.build();
default_map.add_reg(Ra, ‘h0100);
default_map.add_reg(Rb, ‘h0200);
begin
alias_RaRb RaRb;
RaRb = alias_RaRb::type_id::create("RaRb",,get_full_name());
RaRb.configure(Ra, Rb);
end
endfunction
endclass
2 instances of register
Aliased register at
additional address offsets
The 3rd class definition in
next slide
54. Cadence Confidential
Aliased Register: SystemVerilog Code
55
class write_also_to_F extends uvm_reg_cbs;
local uvm_reg_field m_toF;
function new(uvm_reg_field toF);
m_toF = toF;
endfunction
virtual function void post_predict(uvm_reg_field fld, uvm_reg_data_t value,
uvm_predict_e kind,uvm_path_e path,uvm_reg_map map);
if (kind != UVM_PREDICT_WRITE) return;
void'(m_toF.predict(value, -1, UVM_PREDICT_WRITE, path, map));
endfunction
endclass
class alias_RaRb extends uvm_object;
protected reg_Ra m_Ra;
protected reg_Rb m_Rb;
……
function void configure(reg_Ra Ra, reg_Rb Rb);
write_also_to_F F2F;
m_Ra = Ra; m_Rb = Rb;
F2F = new(Rb.F1);
uvm_reg_field_cb::add(Ra.F1, F2F);
endfunction : configure
endclass : alias_RaRb
Aliasing function provided in 3rd class
that link the 2 register type instance
55. Cadence Confidential
Comments about the SV Register Code
• Register code uses SystemVerilog classes
– Scalable memory and performance wise
– Easy to add user defined coverage and generation
– Most of it is not intended to be read by users
• Defines lots of automation
– Leverages UVM automation
– Automatic coverage groups and constraints
• uvm_reg uses UVM factory for register allocation
– Can easily extend register definitions by instance or by type
without re-describing the address map hierarchy
56
57. Cadence Confidential
Lab 1 – Register File Definition and Generation
• For this lab, you will be exploring the register generation
capability:
– Run the IP-XACT parser to convert an xml/spirit file to
SystemVerilog register definitions file.
– Add a register to the XML file and review your results
• Refer to slide 2 to set up the SOC Kit
% cd $MY_WORK_AREA
% $SOCV_KIT_HOME/bin/install_uvm –reg_lab1
% cd reg_lab1
58
58. Cadence Confidential
Lab 1 – Register File Definition and Generation
• Examine the provided spirit file “uart_ctrl_regs.xml”
– Identify the main elements: memoryMaps, memoryMap,
addressBlock, register and field
– Set environment variable IREG_GEN according to
README.lab1
– Use the parser to generate SystemVerilog code:
% $IREG_GEN/bin/iregGen –i uart_ctrl_regs.xml –o uart_ctrl_regs.sv
– Review the generated code
59
59. Cadence Confidential
2. Using Eclipse or another editor to add clock divisor byte 0 register
– Add a RW 8 bits register definition named ua_div_latch0 with Address
0x00
• The definition can be added anywhere in the file, but please add it
after the ua_lcr register and before ua_div_latch1. (Look for the
LAB1 note in the file)
Register: Divisor Latch byte 0 Register Offset: 0x00
Reg Name: ua_div_latch0 Access: read-write
ResetVal: 0x01
Fields: [7:0] div_val (clock divisor value)
• You will also need to include the following vendorExtension:
type: ua_div_latch0_c (register_class_name)
constraint: c_div_val { div_val.value == 1; }
Lab 1 – Adding a Register to the XML File
div_val[7:0] Reset Value = 0x00
60
60. Cadence Confidential
3. Generate SystemVerilog file using:
% $IREG_GEN/bin/iregGen -i <ipxact_file_name> [-o <sv_file_name>]
4. Use the register file in a simple test.
% run.me
• The test builds the register database and calls the reset() to reset
all registers. Review the irun.log file to verify that the
ua_div_latch0 reset value is correctly set.
Lab 1 – Generating the SystemVerilog Code
End of Lab 1!
61
61. Cadence Confidential
Agenda
• Why Model Registers?
• Terminology
• Using uvm_reg to verify a DUT
– Capture DUT register attributes
– Connecting the uvm_reg components in a testbench
– Control register scenarios
– Use uvm_reg for checking and coverage
• Summary
62
62. Cadence Confidential
uvm_reg Connection Requirements
• Connecting uvm_reg to BUS UVC should be as
effortless as possible
• Should be able to replace BUS interfaces
• Should have a passive mode of operation
• BUS UVC should not be modified
• Should use TLM for modularity and mixed-language
• Should be possible to drive register-operations
interleaved with bus transactions
63
63. Cadence Confidential
Connecting the Register Database
• The uvm_reg package provides a register sequencer
– Generates and sends register operations
• No need to modify bus sequencer to allow register
operations in parallel to normal bus operation.
– Create an adapter which converts register operations to bus-
level transactions
• Place the register database and register sequencer in
the testbench
– Use standard TLM hook-up mechanism to connect the register
components in the testbench.
• Use the virtual sequencer to control the register
sequencer as required
64
64. Cadence Confidential
65
Testbench
Module UVC
Register Model instantiation and hook-up
dut
APB
master
driver coll
seqr
memctl
mode0
mode2
mode1
mode3
Adapter
object
Virtual
Sequencer
Register Model
Register Block
0x1000 mode0
mode1
mode2
mode3
Implement adapter
bus2reg and reg2bus
tasks
Place register model, adapter,
module UVC and register
sequencer in the testbench.
Predictor
Component
status
mem_inst
memory
32x4096
status
0x0000
0x0FFF
memory
(4K)
0x1001
0x1002
0x1003
0x1010
.
.
.
apb_if
mon
Register
Sequencer
Add the predictor component
to the module UVC
65. Cadence Confidential
Hooking Up the uvm_reg
• Step 1: Define Transaction Adapter
– Define 2 functions: reg2bus() and bus2reg()
– Conversion between a generic read/write bus operation
descriptor(uvm_reg_bus_op) and the protocol specific read/write
transaction descriptor.
• Step 2: In the testbench:
– Integrating the register model
– Integrating bus sequencers
– Predictor integration
66
66. Cadence Confidential
class reg2apb_adapter extends uvm_reg_adapter;
`uvm_object_utils(reg2apb_adapter)
function new(string name = "reg2apb_adapter");
super.new(name);
supports_byte_enables = 1;
provides_responses = 1;
endfunction
virtual function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
apb_rw apb = apb_rw::type_id::create("apb_rw");
apb.kind = (rw.kind == UVM_READ) ? apb_rw::READ : apb_rw::WRITE;
apb.addr = rw.addr; apb.data = rw.data;
return apb;
endfunction
virtual function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);
apb_rw apb;
if (!$cast(apb,bus_item)) begin
`uvm_fatal("NOT_APB_TYPE“, "Provided bus_item is not of the correct type")
return;
end
rw.kind = apb.kind ? UVM_READ : UVM_WRITE;
rw.addr = apb.addr; rw.data = apb.data; rw.status = UVM_IS_OK;
endfunction
endclass
Transaction Adapter
reg2bus function
Bus2reg function
67
Step 1: Transaction Adapter
If bus protocol support byte lane enables
If bus driver returns responses
67. Cadence Confidential
68
Testbench
Module UVC
Step 2: Testbench Activities
dut
APB
master
driver coll
seqr
memctl
mode0
mode2
mode1
mode3
Adapter
object
Virtual
Sequencer
Register Model
Register Block
0x1000 mode0
mode1
mode2
mode3
Implement register
sequencer and virtual
sequencer
Place register model, adapter,
module UVC and register
sequencer in the testbench.
Predictor
Component
status
mem_inst
memory
32x4096
status
0x0000
0x0FFF
memory
(4K)
0x1001
0x1002
0x1003
0x1010
.
.
.
apb_if
mon
Register
Sequencer
Add the predictor component
to the module UVC
68. Cadence Confidential
Integrating a Register Model
class uart_ctrl_tb extends uvm_env;
// Testbench components – interface and module UVCs, Virtual Sequencer, config, etc
uart_ctrl_virtual_sequencer virtual_sequencer; // multi-channel sequencer
apb_pkg::apb_env apb0; // APB UVC
uart_pkg::uart_env uart0; // UART UVC
uart_ctrl_env uart_ctrl0; // MODULE UVC
uart_ctrl_config cfg;
//Declare register components
uart_ctrl_reg_model_c reg_model; // Register Model – generated by the parser
reg_to_apb_adapter reg2apb; // Adapter Object - REG to APB
// Enable automation for uart_ctrl_tb
`uvm_component_utils_begin(uart_ctrl_tb)
`uvm_field_object(reg_model, UVM_DEFAULT | UVM_REFERENCE)
`uvm_field_object(reg2apb, UVM_DEFAULT | UVM_REFERENCE)
`uvm_field_object(cfg, UVM_DEFAULT)
`uvm_component_utils
// Testbench code continued on the next slide…
69
Register model declaration
Transaction adapter declaration
69. Cadence Confidential
Testbench Components build_phase() method
function new(input string name, input uvm_component parent=null);
super.new(name,parent);
endfunction
// class apb_uart_tb extends uvm_env …
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
// Configure and build UVCs
…
//Build register components
if (reg_model == null) begin
reg_model = uart_ctrl_reg_model_c::type_id::create("reg_model");
reg_model.build(); //NOTE: not same as build_phase: reg_model is an object
reg_model.lock_model();
end
reg2apb = reg_to_apb_adapter::type_id::create("reg2apb");
endfunction : build_phase
// Testbench code continued on the next slide…
Register model build.
To enable reuse, first check if it’s
build at higher level.
70
Transaction adapter creation
70. Cadence Confidential
Testbench Components connect_phase()
Method
// class uart_ctrl_tb extends uvm_env;
function void connect_phase(uvm_phase);
super.connect_phase(phase);
// Hook up virtual sequencer,TLM ports, etc
// . . .
// UVM_REG Connections
reg_model.default_map.set_sequencer(apb0.master.sequencer, reg2apb);
……
endfunction : connect_phase
Register sequence running
on APB bus sequencer
71
71. Cadence Confidential
Handling Reset
• Whenever the DUT is going through hard reset, its
registers are set to predefined values according to the
spec
– Reset value for each field is provided in IP-XACT format
– Shadow registers in the testbench should be reset as well
72
72. Cadence Confidential
Handling Reset - Example
class my_testbench extends uvm_env;
. . .
// Task to reset shadow register database
task reset_reg();
forever begin
wait (tb_top.reset === 1);
uvm_report_info(get_type_name(), “Resetting Shadow Registers");
reg_model.reset();
uvm_report_info (get_type_name(), “Reset Complete");
wait (tb_top.reset == 0);
end
endtask
task run();
fork
reset_reg();
join_none
…
Detect hard reset
Forgetting the reset is a common hook up mistake
73
73. Cadence Confidential
Lab 2: Adding the Register Components
• For this lab, you will be hooking up the register components in the
uart_ctrl design.
• Objectives:
– Review the transaction adapter and register model
– Hook up the required components in the testbench
– Handling reset
• Refer to slide 2 to set up the SOC Kit
% cd $MY_WORK_AREA
% $SOCV_KIT_HOME/bin/install_uvm –reg_lab2
% cd reg_lab2
74
74. Cadence Confidential
Lab 2: Adding the Register Components
• First, review the register definitions for this lab.
% cd $SOCV_KIT_HOME/soc_verification_lib/sv_cb_ex_lib/uart_ctrl/sv
– Review the uart_ctrl_reg_model.sv file in this directory. It should be
similar to the file you generated for lab 1.
• Work in the $MY_WORK_AREA/reg_lab2 directory
% cd $MY_WORK_AREA/reg_lab2
75
75. Cadence Confidential
Lab 2A: Finish transaction adapter
• Edit the reg_to_apb_adapter.sv file in this directory.
– In transaction adapter file, 2 functions should be defined, reg2bus
() and bus2reg().
– reg2bus() is finished, please finish bus2reg() function.
• NOTES:
• Search for LAB2A comments in your lab database files.
76
76. Cadence Confidential
Lab 2B: Adding register model to testbench
• Edit the uart_ctrl_tb.sv, uart_ctrl_env.sv files in this
directory.
– Declare register model (uart_ctrl_reg_model_c reg_model) and
transaction adapter (reg_to_apb_adatper reg2apb)
– In the build_phase() method,
• Build the register model: reg_model, don’t forget to lock it after
building it.
• Build the transaction adapter here too.
• NOTES:
• Search for LAB2B comments in your lab database files.
77
77. Cadence Confidential
Lab 2B: Adding register model to testbench
• Continue to edit the uart_ctrl_tb.sv, uart_ctrl_env.sv
– In the connect_phase() method,
• Register APB bus sequencer and the transaction adapter (reg2apb)
with the default_map in the register model.
• Connect the pointer for reg_model in virtual sequencer and uart_ctrl
environment to reg_model.
– In the run_phase method
• Print reg_model topology and initial values for all registers.
• NOTE: Remember to search for LAB2B comments
78
78. Cadence Confidential
Lab 2B: Adding register model to testbench
• At this point, you should be able to use the Makefile to
compile/elaborate and simulate the testbench with the registers
included.
• The default test in the Makefile should be executed and the results
reviewed (irun.log).
$SOCV_KIT_HOME/soc_verification_lib/sv_cb_ex_lib/uart_ctrl/tb/scripts/run.sh
End of Lab 2!
79
79. Cadence Confidential
Lab 2C: Properly Handling Reset
• You will eventually have issues with reset unless you put in code to
handle a hard reset.
• Edit the uart_ctrl_tb.sv file in this directory.
(NOTE: Search for LAB2C in your lab database files)
– Finish reset_reg() task to call the reset() for the register model and print the
register model and it’s reset value.
– Change run_phase() to add call reset_reg there.
• Re-run your test in the $MY_WORK_AREA/reg_lab2 directory:
$SOCV_KIT_HOME/soc_verification_lib/sv_cb_ex_lib/uart_ctrl/tb/sc
ripts/run.sh
End of Lab 2!
80
80. Cadence Confidential
Agenda
• Why Model Registers?
• Terminology
• Using uvm_reg to verify a DUT
– Capture DUT register attributes
– Connecting the uvm_reg components in a testbench
– Control register scenarios
– Use uvm_reg for checking and coverage
• Summary
81
81. Cadence Confidential
Controlling Register Scenarios
• Ideally should not invent a new sequence mechanism
– Use UVM sequences
• Should be able to control both register operations and
register’s attributes
– Read/write, by address/value, with constraint or not,
backdoor/bus, random/directed, with allocation/without
• Should be able to define generic sequences
– Have a built-in package sequence library
• Need to support module-to-system sequences reuse
– Module level sequences can be combined into a system level
configuration sequence
82
82. Cadence Confidential
uvm_reg run-time Tasks
• User may need to apply
– Drive device initial configuration
• May need to configure devices multiple times during a run
– Normal run-time operations of reading and moving values
between registers and other address locations. For example:
• Poll status registers
• Serve interrupts
• Copy values from registers to memory locations
• uvm_reg leverages the standard sequence mechanism
to enable these operations making them
– Efficient
– Flexible
– Reusable
83
83. Cadence Confidential
Access APIs for Memories, Registers, Fields
• write()/read(): Write/read immediate value to DUT.
• set()/get() : Sets or gets desired value for the register model.
• randomize() : Using the randomize() method copies the
randomized value in the uvm_reg_field::value property into the
desired value of the mirror by the post_randomize() method.
• update() : Invokes the write() method if the desired value
(previously modified using set() or randomize()) is different from
the mirrored value.
• mirror() : Invokes the read() method to update the
mirrored value based on the read back value. mirror() can also
compare the read back value with the current mirrored value
before updating it.
84
* Use BACKDOOR mode to directly access values (e.g. HDL path)
* Update and mirror API can be called on container (block) too
84. Cadence Confidential
class blk_seq extends uvm_reg_sequence;
`uvm_object_utils(blk_seq)
my_rf model;
virtual task body();
uvm_status_e status;
int data;
model.config.write(status, ‘h12, .parent(this));
model.config.write(status, ‘h34, UVM_BACKDOOR, .parent(this));
model.config.read(status, data, UVM_BACKDOOR, .parent(this));
model.my_mem.write(status, ‘h8, ‘h1234_5678, .parent(this));
void'(model.randomize());
endtask : body
endclass: blk_seq
Creating Sequences
Frontdoor Write
Backdoor Write
Backdoor Read
Seq’s container
Memory frontdoor
The do actions are hidden with
read/write routines
It is useful to combine positional
and named arguments binding
While it is possible to mirror the shadow from sequences it is not
recommended (see on checking and monitoring)
85
85. Cadence Confidential
class my_test extends uvm_test;
block_env env;
virtual function void run();
my_reg_sequence seq = my_reg_sequence::type_id::create(“seq”,this);
seq.model = env.reg_model;
seq.start(env.apb.master);
endfunction
endclass: my_test
Running Sequences
• To run the register sequence, assign the sequence model
property and start it on the bus sequencer.
Assign register model for register
sequencer
Start register sequencer on bus
sequencer
86
86. Cadence Confidential
Lab 3: Register Sequences
• For this lab, you will be exploring register sequences for the
uart_ctrl design from our SOC Verification Kit
• Objectives
– Create a register sequence
– Execute a register sequence in conjunction with virtual sequences
• Refer slide 2 to set up the SOC Kit
% cd $MY_WORK_AREA
% $SOCV_KIT_HOME/bin/install_uvm –reg_lab3
% cd reg_lab3
87
87. Cadence Confidential
Lab 3: Register Sequences
• Work in the $MY_WORK_AREA/reg_lab3 directory.
• Open the uart_ctrl_reg_seq_lib.sv file and review the
existing sequences:
apb_config_reg_seq: configure the UART register via APB sequencer
uart_ctrl_config_reg_seq: configures the UART registers
uart_ctrl_1stopbit_reg_seq – configures the UART for 1stopbit
ua_lab3_seq – simple sequence for the register sequencer. For now this
sequence does nothing.
88
88. Cadence Confidential
Lab 3A: Observe Register Sequencer Behavior
• Review the test: apb_uart_rx_tx.sv
– Look for TEST: apb_uart_rx_tx
– It sets the default sequence for the virtual sequencer
(concurrent_u2a_a2u_rand_trans_vseq)
• Review virtual sequence library
uart_ctrl_virtual_sequence_lib.sv
– Look for virtual sequence: concurrent_u2a_a2u_rand_trans_vseq
– It start a register sequence : uart_ctrl_config_reg_seq
• Now run the test:
% $SOCV_KIT_HOME/soc_verification_lib/sv_cb_ex_lib/uart_ctrl/tb/scripts/run.sh -test
apb_uart_rx_tx
• You should see several read/write to the registers in the
irun.log file.
89
89. Cadence Confidential
Lab 3B: Write a New register Sequence
• Open uart_ctrl_reg_seq_lib.sv and review the SEQUENCE:
ua_lab3_seq
– Edit the ua_lab3_seq
– This sequence basically does the same thing as uart_ctrl_config_reg_seq,
but after each write to register is followed by a read back.
• Open uart_ctrl_virtual_seq_lib.sv and edit virtual sequence
concurrent_u2a_a2u_rand_trans_vseq
– In it, instead of start register sequence uart_ctrl_config_reg_seq , we will
start register sequence ua_lab3_seq
• Re-run the test:
% $SOCV_KIT_HOME/soc_verification_lib/sv_cb_ex_lib/uart_ctrl/tb/scripts/run.sh -test
apb_uart_rx_tx
• Verify that your registers was correctly written and read.
90
End of Lab 3!
90. Cadence Confidential
Built-in Sequences
• In many cases users want to perform operations on subset or all
registers in address map/reg-file
– E.g. write to all writeable registers in a reg-file
• uvm_reg provide some generic built-in sequences
• Registers or memory with certain attribute are not applied for some
sequences
– E.g All built-in sequence don’t apply to register or memory with
NO_REG_TESTS or NO_MEM_TESTS attributes defined.
91
91. Cadence Confidential
UVM Built-in Sequences for registers
Built-in-sequence Description Skip attribute
uvm_reg_hw_reset_seq Reads all of the register in a block and check
their POR value.
NO_HW_RESET_T
EST
uvm_reg_single_bit_bash_seq
uvm_reg_bit_bash_seq
Sequentially walks ‘0’ and ‘1’, checking if
appropriately set or cleared.
NO_REG_BIT_BAS
H_TEST
uvm_[reg|mem]_single_access_seq
uvm_[reg|mem]_access_seq
Write frontdoor and read (checks) backdoor, later
writes backdoor and reads (checks) frontdoor.
NO_[REG|MEM]_A
CCESS_TEST
uvm_mem_single_walk_seq
uvm_mem_walk_seq
Write a walking pattern into the memory then
checks read back with the expected value.
NO_MEM_WALK_T
EST
uvm_[reg|mem]_shared_acc
uvm_reg_mem_shared_access_seq
ess_seq
For each address map, writes the register |
memory via one map then confirms written by
reading it from all other address maps.
NO_SHARED_ACC
ESS_TEST
uvm_reg_mem_hdl_path_seq check that the specified backdoor paths are
indeed accessible by the simulator.
uvm_reg_mem_built_in_seq Execute all the built-in sequence
Complete list can be found in UVM User Guide
92
92. Cadence Confidential
Cadence has created new built-in-sequence library which allows more
automation and does additional filtering to allow selection or removal of
registers. Sequences can be configured to access front-door or backdoor
(all combinations).
`ncroot`/tools/uvm-1.1/uvm_lib/uvm_sv/src/cdns_additions/reg
Built-in-sequences – Cadence Extension
using conditions
using names
using addresses
using addr range
using string attributes
Filters
setup
post_setup
print_configs
main
post_main
Sequence body
Register rd/wr
happens here
User hook
User hook
Register selection
happens here
Sequence parameters
gets printed here
get_all_registers
get_configs
filter_registers
Registers Selection
93
93. Cadence Confidential
Cadence’s Built-in Sequences
Built-in-sequence Description Skip attribute
uvm_reg_built_in_read_all_regs_seq
Reads all of the register in a block. It is assumed that
explicit monitor does register value checking NO_RD_REG_TESTS
uvm_reg_built_in_write_all_regs_seq
This sequence is going to write all registers with
random value. Sequence has a flag to direct the value
to be specific value, than random.
NO_WR_REG_TESTS
uvm_reg_built_in_wr_follow_rd_seq
This sequence is going to first write register and then
immediately read that register. For writing, sequence
has a flag to direct the value to be specific value, than
random.
NO_RD_REG_TESTS
or
NO_WR_REG_TESTS
uvm_reg_built_in_aliasing_seq
It writes a random value to a register and reads all the
other registers to make sure the write did not affect
them. It does this for each and every register in the
block
NO_RD_REG_TESTS
or
NO_WR_REG_TESTS
uvm_reg_generate_access_file_seq
This sequence can be used to generate access file for
backdoor access optimization
uvm_reg_built_in_all_seq
This sequence is going to call all built-in-sequences
one-by-one for a container Individual skip
attributes
94
94. Cadence Confidential
Agenda
• Why Model Registers?
• Terminology
• Using uvm_reg to verify a DUT
– Capture DUT register attributes
– Connecting the uvm_reg components in a testbench
– Control register scenarios
– Use uvm_reg for checking and coverage
• Summary
95
95. Cadence Confidential
• Register checking and coverage are useful
– Register field values mapped into DUT operation modes
– Consistency checking against mirror/reference can identify
errors regardless of the testbench implementation or DUT
complexity
• The first question to be asked is where to place the
monitoring logic. Is it?
– A. In the sequences?
– B. Passively via passive monitor?
• Separation of injection and monitoring path is one of the
basic concepts of UVM
– We repeat the motivation in the context of register modeling
Registers’ Checking and Coverage
96
96. Cadence Confidential
• Traditionally a directed testing approach
– Update and compare as part of the sequence body
– Advantage: natural for directed and check is done in one scope
• Disadvantageous
– The check is valid only for this specific operation
• Not in other operations or other sequences
– What if I’m not driving the bus?
• Could be other VIP or even the DUT
• Multiple register value assumptions grow stale
– Does not support vertical reuse
• Bus may become internal in larger system
• Different system-level sequence might be produced
– The current library adjust the desired value upon randomization
• What happens in case of pipelines, incomplete transaction, storing
continuation for later submission (e.g. DMA tasks).
Monitoring and Checking in the Stimuli
Implicit Predictor
97
97. Cadence Confidential
1. A predictor object needs to be created and associated with bus monitor
2. Predictor’s transaction-adapter needs to be set according to bus protocol
3. Once the transaction reaches predictor, ‘map’ inside predictor picks up
register associated at that address and does prediction
The Recommended approach:
Explicit Predictor
Sequencer Driver
Monitor
Bus UVC
Bus
Predictor
Map
Adapter
addr
reg.predict(data)
data If
read
Compare
With
shadow
yes
no
98
98. Cadence Confidential
Explicit monitoring - Integrating a Predictor
class uart_ctrl_tb extends uvm_env;
// Testbench components – interface and module UVCs, Virtual Sequencer, config, etc
uart_ctrl_virtual_sequencer virtual_sequencer; // multi-channel sequencer
apb_pkg::apb_env apb0; // APB UVC
uart_pkg::uart_env uart0; // UART UVC
uart_ctrl_env uart_ctrl0; // MODULE UVC
uart_ctrl_config cfg;
//Declare register components
uart_ctrl_reg_model_c reg_model; // Register Model – generated by the parser
reg_to_apb_adapter reg2apb; // Adapter Object - REG to APB
uvm_reg_predictor#(apb_transfer) apb_predictor; //Predictor - APB to REG
// class apb_uart_tb extends uvm_env …
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
// Configure and build UVCs
…
apb_predictor = uvm_reg_predictor#(apb_transfer)::type_id::create("apb_predictor", this);
reg2apb = reg_to_apb_adapter::type_id::create("reg2apb");
endfunction : build_phase
99
Predictor Component
Create predictor and adapter
99. Cadence Confidential
Testbench Components connect_phase()
Method
// class uart_ctrl_tb extends uvm_env;
function void connect_phase(uvm_phase);
super.connect_phase(phase);
// Hook up virtual sequencer,TLM ports, etc
// . . .
// UVM_REG Connections
apb_predictor.map=reg_model.default_map;
apb_predictor.adapter=reg2apb;
apb0.bus_monitor.item_collected_port.connect(apb_predictor.bus_in);
endfunction : connect_phase
Connect address map
and adapter to predictor
100
When bus transfer is
observed
pass it to predictor
100. Cadence Confidential
• As was described before passive monitoring deploys
automatic checking
– Updates register value upon write operation
– Check register value on read operations
• How can I avoid comparing fields?
– Use the bit mask as part of the register attribute input
• How do we verify read-only registers? Example, reflect
interrupt status
– Recommended options: update the value on the shadow model
– Less recommended: use the mask and check in sequences
• This one suffers from all the disadvantages of checking from the
injection path
Using the Shadow Register Model for Checking
101
101. Cadence Confidential
Testbench
102
Interrupt Example
UART Module
UART DUT
APB
Interface
Mode
Switch
Control/Interrupt
Logic
Rx FIFO Receiver
Transmitter
Tx FIFO
Control/Status
Registers
rdb
uart_cover
(white box
coverage)
interrupt
int
status
// within the monitor
virtual task update_reg_model();
forever begin
@interrupt;
set_reg_val_by_name(“csr.interrupt”, 1);
end
endtask: update_reg_model
A set of routines exist
to modify register values
103. Cadence Confidential
Adding/Modifying Coverage Groups
• We do not recommend modifying the generated
SystemVerilog
• Use the factory to add coverage extensions
class cov_control_reg extends control_reg_c ;
covergroup cross_control_cg;
cross rxen.value, stpb.value;
endgroup
function void sample();
super.sample();
cross_control_cg.sample();
endfunction
endclass
Note that you must use a
different coverage group name
104
104. Cadence Confidential
Lab 4: Adding the Predictor
• For this lab, you will be hooking up the predictor components in the
uart_ctrl design.
• Objectives:
– Hook up the required components in the testbench
• Refer to slide 2 to set up the SOC Kit
% cd $MY_WORK_AREA
% $SOCV_KIT_HOME/bin/install_uvm –reg_lab4
% cd reg_lab4
105
105. Cadence Confidential
Lab 4: Adding register model to testbench
• Edit the uart_ctrl_tb.sv, uart_ctrl_env.sv files.
– Declare predictor(uvm_reg_predictor#(apb_transfer)
apb_predictor)
– In the build_phase() method,
• Build the predictor: apb_predictor
– In the connect_phase() method,
• Connect the register model and transaction adapter (reg2apb) to
predictor.
• Connect the analysis port from APB monitor to TLM port of predictor.
This is how predictor get all the transactions.
• Change prediction mode from implicit to explicit by calling
set_auto_predict(0)
• NOTES:
• Search for LAB4 comments in your lab database files.
106
106. Cadence Confidential
Lab 4: Adding predictor to testbench
• At this point, you should be able to use the Makefile to
compile/elaborate and simulate the testbench with the registers
included.
• The default test in the Makefile should be executed and the results
reviewed (irun.log).
$SOCV_KIT_HOME/soc_verification_lib/sv_cb_ex_lib/uart_ctrl/tb/scripts/run.sh
End of Lab 4!
107
107. Cadence Confidential
Agenda
• Why Model Registers?
• Terminology
• Using uvm_reg to verify a DUT
– Capture DUT register attributes
– Connecting the uvm_reg components in a testbench
– Control register scenarios
– Use uvm_reg for checking
– Cover register activity
• Summary
108
108. Cadence Confidential
• While the concept of registers is simple and sound, the
library data structure implementation is complex
• User may want to:
– Review register hierarchy and properties
– Current values
– Set break-point on register related events
– Dump values to the waveform
• Cadence has long history with register and memory
automation (vr_ad)
• This is a prototype register viewer which is part of the
cadence additions
Cadence Register Viewer - iregViewer
109
109. Cadence Confidential
The Register Viewer - iregViewer
setenv SIMVISIONOPTS " -memberplugindir dir_path_upto/iregViewer"
setenv SIMVISION_ENABLE_UVM_REG_VIEWER 1
Run simulation in gui with linedebug on. Break after build-done.
110
111. Cadence Confidential
• Technology
– According to users, IES Simulator demonstrated significantly more
scalability than other simulators
– Cadence IPXACT Generator - iregGen
• Supports both the UVM_RGM and the UVM_REG packages (via a
switch)
• IPXACT front-end is proven in many projects
• Supports capabilities that are not yet in the standard library
• Results are tuned for performance and scalability
– Register viewer plug-in - iregViewer
– Cadence extensions – built-in-sequences and extended predictor
• Knowledge and expertise
– Cadence field team and services are familiar with the UVM_REG
new methodology and use model
Why is IES the Best Platform for UVM_REG?
112