Sie sind auf Seite 1von 111

INVENTIVE

UVM Register Layer Classes

June 2013
© 2011-2013 Cadence Design Systems, Inc. All rights reserved worldwide.
Printed in the United States of America.
Cadence Design Systems, Inc., 2655 Seely Avenue, San Jose, CA 95134, USA

Trademarks: Trademarks and service marks of Cadence Design Systems, Inc. (Cadence) contained in this document are attributed
to Cadence with the appropriate symbol. For queries regarding Cadence's trademarks, contact the corporate legal department at the
address shown above or call 800.862.4522.
Open SystemC, Open SystemC Initiative, OSCI, SystemC, and SystemC Initiative are trademarks or registered trademarks of Open
SystemC Initiative, Inc. in the United States and other countries and are used with permission.
All other trademarks are the property of their respective holders.
Restricted Permission: This publication is protected by copyright law and international treaties and contains trade secrets and
proprietary information owned by Cadence. Unauthorized reproduction or distribution of this publication, or any portion of it, may
result in civil and criminal penalties. Except as specified in this permission statement, this publication may not be copied, reproduced,
modified, published, uploaded, posted, transmitted, or distributed in any way, without prior written permission from Cadence. Unless
otherwise agreed to by Cadence in writing, this statement grants Cadence customers permission to print one (1) hard copy of this
publication subject to the following conditions:
The publication may be used only in accordance with a written agreement between Cadence and its customer;
The publication may not be modified in any way;
Any authorized copy of the publication or portion thereof must include all original copyright, trademark, and other proprietary notices
and this permission statement;
The information contained in this document cannot be used in the development of like products or software, whether for internal or
external use, and shall not be used for the benefit of any other party, whether or not for consideration
Disclaimer: Information in this publication is subject to change without notice and does not represent a commitment on the part of
Cadence. The information contained herein is the proprietary and confidential information of Cadence or its licensors, and is supplied
subject to, and may be used only by Cadence's customer in accordance with, a written agreement between Cadence and its
customer. Except as may be explicitly set forth in such agreement, Cadence does not make, and expressly disclaims, any
representations or warranties as to the completeness, accuracy or usefulness of the information contained in this document.
Cadence does not warrant that use of such information will not infringe any third party rights, nor does Cadence assume any liability
for damages or costs of any kind that may result from use of such information.
Restricted Rights: Use, duplication, or disclosure by the Government is subject to restrictions as set forth in FAR52.227-14 and
DFAR252.227-7013 et seq. or its successor.

2 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 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 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 Cadence Confidential
Typical System-Level Environment
Many devices are attached to a bus
and have a register set that interfaces
between the DUT and a programmer’s
The CPU controls the entire model
system, by reading and SW Application
writing device registers
SW Device Drivers
SoC
CPU DMA Memory
(DUT)
CPU Bus (AHB)
Bridge
Peripheral Bus (Xbus)
XCore XCore USB Ethernet

From Keyboard To screen From barcode / To / peripheral


Each From contains
credit card reader registers
credit center
which are mapped
to the CPU’s address space.

6 Cadence Confidential
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
7 Cadence Confidential
Verifying a Component of the DUT (XCore)

SoC
(DUT) CPU DMA Memory

CPU Bus Interface CPU Bus (AHB)

Bridge
DUT
Peripheral Bus (Xbus)

XCore XCore
XCore USB Ethernet

Peripheral Interface
8 Cadence Confidential
Configuring Devices Using uvm_reg
Register Register sequence executes
Sequence register operations
Adapter converts
register operations to Adapter
bus transactions Randomize environment
and DUT configuration
APB
Master UVC drives master
bus transactions seqr agent Register Model
driver mon Register Block
0x0000
memory

...
(4K)
dut apb_if 0x0FFF
0x1000 mode0
memctl 0x1001 mode1
0x1002 mode2
mem_inst 0x1003 mode3
mode0 status
0x1010
mode1
memory
mode2 32x4096
mode3 Register model shadows the
status registers, register blocks and
memories in the DUT
9 Cadence Confidential 9
Register Monitoring and Checking
Predictor:receives transactions:
Predictor
Adapter converts bus Write: update the model
transactions back to Adapter Read: compare (and update)
register operations Predictor the register model
Component
APB
master
seqr agent Register Model
A bus monitor captures
driver mon Register Block
transactions on the bus
and sends them via TLM 0x0000
memory Functional coverage

...
(4K) is sampled in the
dut apb_if 0x0FFF
register model
Clear separation 0x1000 mode0
memctl 0x1001 mode1
of injection and 0x1002 mode2
collection path is mode0 mem_inst 0x1003 mode3
0x1010 status
key! mode1
memory
mode2 32x4096 Register model (database) contains
mode3 address map(s) and is placed in the
status testbench. Also holds attributes
and expected values.

10 Cadence Confidential 10
Register Model instantiation and hook-up
Testbench
Module UVC Add the predictor component
Implement adapter Adapter Predictor to the module UVC
bus2reg and reg2bus object Component
tasks

Register APB Register Model


Sequencer master
seqr mon
Register Block
0x0000
memory

...
driver coll
(4K)
0x0FFF
Virtual 0x1000 mode0
Sequencer 0x1001 mode1
apb_if
dut 0x1002 mode2
0x1003 mode3
memctl 0x1010 status

mode0 mem_inst
mode1
memory Place register model, adapter,
mode2 32x4096
module UVC and register
mode3
sequencer in the testbench.
status
12 Cadence Confidential
Registers and Register Operations

Reg-file
0x00 tx_mode Register: Status Reg
0x01 tx_status e error_count
7 6 0
0x02 rx_mode
0x03 rx_status

Register Operation Register


uvm_reg_bus_op: register operation name: rx_status_reg
addr: sized integer fields: error: 1’b1 // flag
kind: READ, WRITE error_cnt: 7’h04
data: the register variable
status: result of transaction

register_sequencer uvm_reg_bus_op: xcore_sequencer transaction:


addr: ’h03 xaddr: ’h03
kind: READ xdata: ‘h84
data: ‘h84 xwr_rd: READ

13 Cadence Confidential
UVM_REG

• 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
Objective: Encourage correct use-model of uvm_reg
to maximize automation and reuse
14 Cadence Confidential
UVM_REG Features

• 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

15 Cadence Confidential
Capturing UVM_REG Model
Following the IP-XACT Hierarchy
• 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
User manually creates reusable
UVM configuration sequences
Users capture their project
Register model in IPXACT

Generated SV code is UVM_reg UVM config


base classes sequences
vendor specific

testbench
Register
Generator
IP-XACT Utility Reg classes
and DB Placed inside a testbench
for randomizing, checking,
Provided by Vendors and coverage

16 Cadence Confidential
Cadence IP-XACT Generator (example)
Command
$IREG_GEN/bin/ireggen –i ipxact_example.xml –d ./out –qt

Output
<++> Cadence iregGen version 1.03
<++> XML parsed. Started decoding
...... Cadence generator options:
<++> Decoding done -i (input file name)
<++> Input File: ./ipxact_example.xml -d (directory for output files)
<++> Number of AddrMaps = 1 -qt (creates a simple test)
<++> 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
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>

17 Cadence Confidential
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 Cadence Confidential
UVM_REG Building Blocks
• All objects extend from uvm_object config_reg
– Allows use of UVM automation features!
f4 f3 f2 f1
• Each field is instance of uvm_reg_field
– Fields have many attributes such as reset value, and access
mode
class config_reg extends uvm_reg;
– Holds three copies of the value: uvm_reg_field f1; // 1-bit
uvm_reg_field f2; // 1-bit
• Mirrored: What we think is in the HW uvm_reg_field f3; // 4-bits
• Value: A value to be randomized uvm_reg_field f4; // 2-bits
endclass : config_reg
• 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
20 Cadence Confidential
Field Access Policies Supported

RO Read-Only W1SRC Write ‘1’ to set and clear-on-read


RW Read-Write W1CRS Write ‘1’ to clear and set-on-read
RC Read-only, Clear-on-read W0SRC Write ‘0’ to set and clear-on-read
RS Set-on-read (all bits become W0CRS Write ‘0’ to clear and set-on-read
‘1’ on read) WO Write-only
WRC Writeable, clear-on-read WOC When written sets the field to ‘0’.
WRS Writable, Sets-on-read Read undeterministic
WC Clear-on-write WOS When written sets all bits to ‘1’.
WS Set-on-write Read undeterministic
WSRC Set-on-write, clear-on-read W1 Write-once. Next time onwards,
WCRS Clear-on-write, set-on-read write is ignored. Read returns
the value
W1C Write ‘1’ to clear bits
WO1 Write-once. Next time onwards,
W1S Write ‘1’ to set bits write is ignored. Read is
W1T Write ‘1’ to toggle bits undeterministic
W0C Write ‘0’ to clear bits DC RW but no check
W0S Write ‘0’ to set bits
W0T Write ‘0’ to toggle bits

21 Cadence Confidential
UVM_REG Building Blocks (Continued)

• A register file extends uvm_reg_file


Register File
– Contains multiple register
definitions 0x04 f4 f3 f2 f1 config

– Each register is offset from a 0x08 ch3 ch2 ch1 ch0 status
common address
0x0C rsvd i3 i2 i1 i0 interrupt
– Useful for reuse at higher
levels of abstraction 0x10 count error_cnt

0x00

• A memory is an instance of uvm_mem 0x01


0x02 memory
– All elements are of the same width . 8x256
– Memory width / depth set in constructor .

0xFF

22 Cadence Confidential
Blocks and Maps
Register Model
• Block (Register Model)

...
0x0000
– Extends from uvm_reg_block class
0x014 Config
– A quasi-static UVM component represents a
“shadow” model of registers/memories in 0x018 Status Reg
0x01C Interrupt File
the system address space
0x020 Error Cnt
– Blocks can be nested

...
– Every block has at least one map 0x800

• Map Memory
8x256
– Extends from uvm_reg_map class 0x8ff

...
– Holds the information required to drive
objects through various sequencer/driver 0x1000
pairs 0x1004 Sub-Block
– Address maps can be nested 0x11ff

...
0xffff

23 Cadence Confidential
UVM_REG Class Diagram
For scalability, no unique
class per field
uvm_reg_block uvm_reg

1..N 1..N
my_block my_reg uvm_reg_field
1..N

Registers are composed


of one or more fields
This is your register uvm_reg_file
model and can contain
sub-blocks 1..N
my_regfile Memories have common
1..N data width/format and
Register files comprise sequential addresses
one or more registers
1..N uvm_mem uvm_mem_mam
uvm_* UVM base class
1..N
my_* User-defined class uvm_reg_map
Map all the registers for a
bus interface

24 Cadence Confidential
Register Declaration Generated by iregGen
Typically does not need to be read by users
class config_reg_c extends uvm_reg; 7 6 2 0

f4 f3 f2 f1 config_reg
rand uvm_reg_field f1;
rand uvm_reg_field f2;
rand uvm_reg_field f3; UVM_REG fields
rand uvm_reg_field f4;
Hard Reset
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); Enables randomization of the field
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"); In the build() method, each field
f4.configure(this, 2, 6, “WO", 0, ‘h0, 1, 1, 1); is created, and then configured
endfunction
Size Offset
`uvm_register_cb(config_reg_c, uvm_reg_cbs)
`uvm_set_super_type(config_reg, uvm_reg)
`uvm_object_utils(config_reg_c) Callback + derivation support

function new (input string name="config_reg_c");


super.new(name, 8, UVM_NO_COVERAGE);
endfunction : new
Cadence Confidential
endclass : config_reg_c Reg Width
25
Memory Declarations
IPXact Definition

memory256 (8x256 memory) <spirit:addressBlock> <!– 8x256 Memory-->


7 0 <spirit:name>memory256</spirit:name>
0x00 <spirit:baseAddress>0x100</spirit:baseAddress>
0x01
0x02 <spirit:range>256<</spirit:range>
<spirit:width>8</spirit:width>
...

<spirit:usage>memory</spirit:usage>
<spirit:volatile>false</spirit:volatile>
0xff <spirit:access>read-write</spirit:access>
</spirit::register>

class memory256_c extends uvm_mem;


`uvm_register_cb(memory256_c, uvm_reg_cbs)
`uvm_set_super_type(memory256_c, uvm_mem) iregGen generated
`uvm_object_utils(memory256_c)
function new (input string name=“memory256_c"); UVM_REG code
super.new(name, ‘h100, 8, “RW”, UVM_NO_COVERAGE);
endfunction : new
endclass : memory256_c
Mem size Data width

26 Cadence Confidential
Register File and Register Model
Generated by the iregGen script
class memctl_rf_c extends uvm_reg_block;

rand mode_reg_c mode_reg;


rand config_reg_c config_reg; Registers (can also
contain fields)
virtual function void build();
// create and configure each register
// specify address offset and hdl_path for backdoor access
endfunction

// constructor and uvm_object_utils


The register model, memctl_model_c,
endclass : memctl_rf_c is placed in the testbench and configured

class memctl_model_c extends uvm_reg_block;

rand memctl_rf_c memctl_rf; Register file, memory


rand memory256_c memory256; (can also contain fields)
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

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 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.

* Update and mirror API can be called on container (block) too

29 Cadence Confidential
Register sequencer and sequences A reference to the register
model for reg sequences
• Register sequencer is an UVM
sequencer class memctl_reg_sequencer extends uvm_sequencer;
• Its sequence item is a `uvm_component_utils(memctl_reg_sequencer)
uvm_reg_bus_op
// Contains a pointer to the register model
– And not a sequence of registers memctl_reg_model_c reg_model;

– The operation itself is protocol- function new( string name, uvm_component parent);
neutral super.new(name, parent);
endfunction

endclass : memctl_reg_sequencer

Register sequencer Register operation sequences

Operation to perform
uvm_reg_bus_op
addr on a specific register
kind
data Register
Fields
The register to be Attributes

30 Cadence Confidential
accessed
Creating Register Sequences
class blk_seq extends uvm_reg_sequence;
my_regfile model;
Pointer to the register model container
`uvm_object_utils(blk_seq)
function new ( string name=“blk_seq“ );
super.new(name); Note that there are read/write
endfunction : new tasks that cover the do items
virtual task body();
uvm_status_e status;
int data; Frontdoor Write
model.config.write(status, ‘h12, .parent(this)); Backdoor Write
model.config.write(status, ‘h34, UVM_BACKDOOR, .parent(this));
model.config.read(status, data, UVM_BACKDOOR, .parent(this)); Backdoor Read
model.my_mem.write(status, ‘h8, ‘h1234_5678, .parent(this)); Memory frontdoor
void'(model.randomize());
model.update(status, UVM_BACKDOOR, .parent(this)); Container level
model.mirror(status, UVM_CHECK, UVM_BACKDOOR, .parent(this)); Backdoor update
endtask : body
endclass : blk_seq Container level
Cadence Confidential
Backdoor mirror
31
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 Cadence Confidential
UART DUT and Verification Environment
Module Verification
Component
UVM Testbench Scoreboard
Imitates external
Programs the Interface & white-box device by
UART and coverage
generating frames
transfers traffic

UART DUT (Verilog RTL)


txd
Tx FIFO Transmitter
APB APB APB Mode UART
UART
Verification Interface Switch Serial Verification
Component Rx FIFO Receiver rxd Component

Control/Status Control/Interrupt
Registers Logic

Multi-channel controller
Controls APB and Tests indicate which
UART components stimulus sequences to
Test 1 Test 2 Test 3 execute

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 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 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 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 Cadence Confidential
Sample UART DUT Registers Specification
Address 7 6 5 4 3 2 1 0
0x00 DIV_LATCH0 div_val

0x01 DIV_LATCH1 div_val

0x02 FIFO_CTRL trig_level txcr rxcr

0x03 INT_ENABLE sts l_sts tdata rdata

0x04 INT_ID bit3 bit2 bit1 prio

0x05 LCR acc brk pstk pevn pen stop_bits clen

Addr Name Size Access Reset


0x00 DIV_LATCH0 8 RW 0x00
0x01 DIV_LATCH1 8 RW 0x00
0x02 FIFO_CTRL 8 WO 0xC0
0x03 INTR_ENABLE 8 RW 0x00
0x04 INTR_ID 8 RO 0xC1
0x05 L_CTRL 8 RW 0x03

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
...
Cadence Confidential
IP-XACT Format – Vendor Extensions
<!-- FIELD VENDOR EXTENSIONS-->
<spirit:vendorExtensions>
<!-- collect_coverage: cov_all, cov_none, cov_update, cov_compare_and_update -->
• <vendorExtensions:collect_coverage>
The SPIRIT IP-XACT standard input format was
cov_all</vendorExtensions:collect_coverage>
incomplete for users needs
</spirit:vendorExtensions>
<!-- REGISTER VENDOR EXTENSIONS -->
– For example constraints, coverage,
<spirit:vendorExtensions>
backdoor path etc’ had to be
<!-- type:introduced
Optional - default is register_name -->
– IP-XACT supports
<vendorExtensions:type> vendor
control_reg_c extensions
</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:


$IREG_GEN/bin/iregGen –i ipxact_example.xml –d ./out –qt
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 Cadence Confidential
iregGen : ipXact to System-Verilog generator

$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

42 Cadence Confidential
Register Declaration Generated by iregGen
Typically does not need to be read by users
class config_reg_c extends uvm_reg; 7 6 2 0

f4 f3 f2 f1 config_reg
rand uvm_reg_field f1;
rand uvm_reg_field f2;
rand uvm_reg_field f3; UVM_REG fields
rand uvm_reg_field f4;
Hard Reset
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); Enables randomization of the field
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"); In the build() method, each field
f4.configure(this, 2, 6, “WO", 0, ‘h0, 1, 1, 1); is created, and then configured
endfunction
Size Offset
`uvm_register_cb(config_reg_c, uvm_reg_cbs)
`uvm_set_super_type(config_reg_c, uvm_reg)
`uvm_object_utils(config_reg_c) Callback + derivation support

function new (input string name="config_reg_c");


super.new(name, 8, UVM_NO_COVERAGE);
endfunction : new
43
endclass : config_reg_c
Cadence Confidential
Reg Width
Register File Declaration
Generated by the iregGen script

class memctl_rf_c extends uvm_reg_block;

rand mode_reg_c mode_reg; Registers (can also contain fields)


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”); In the build() method, each register
mode_reg.build(); is created, and then configured
config_reg.configure(this, null, “config_reg”);
config_reg.build(); hdl_path for backdoor access
// 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”); A default map is created with
endfunction address offset information

`uvm_object_utils(memctl_rf_c)
function new (input string name=“memctl_rf_c"); Address offset
super.new(name, UVM_NO_COVERAGE);
endfunction : new
endclass : memctl_rf_c

44 Cadence Confidential
Register Block Declaration (Register Model)
Generated by the iregGen script
class memctl_reg_model_c extends uvm_reg_block;

rand memctl_rf_c memctl_rf;


rand memory256_c memory256; Register file, memory
(can also contain fields)
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(); hdl_path for backdoor access
memctl_rf.lock_model();
default_map.add_submap(memctl_rf.default_map, ‘h1000”); Address offset for register file
// MEMORY
memory256 = memory256_c::type_id::create(“memory256”);
memory256.configure(this, “mem_inst.memory”); hdl_path for backdoor access
memory256.build();
default_map.add_mem(memory256, ‘h0000, “RW”); Address offset for memory
set_hdl_path_root(“top.dut”);
this.lock_model();
endfunction
Root hdl_path for register model
`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

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
HDL path
end Offset

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

Mapped Registers Indirect Registers


0x03 0x00
0x04 addr_reg ‘h0002 0x01
0x05 data_reg ‘h3489 0x02 ‘h3489
0x06 0x03

47 Cadence Confidential
Indirect Registers: IPXACT Code
Note: Indirect address
<spirit:register> <!– INDIRECT DATA REGISTER--> registers are declared
<spirit:name>ireg</spirit:name> like normal registers
<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>
address register
<vendorExtensions:indirect_addr_reg>addr_reg</vendorExtensions:indirect_addr
<vendorExtensions:array>
<vendorExtensions:x_from>1</vendorExtensions:x_from>
offset value
<vendorExtensions:x_to>4</vendorExtensions:x_to>
<vendorExtensions:offset_calc>'h0+x-1</vendorExtensions:offset_calc>
</vendorExtensions:array>
</spirit:vendorExtensions>
</spirit:register>

48 Cadence Confidential
Indirect Register
class my_rf_t extends uvm_reg_block;
Indirect address register
rand addr_reg_t addr_reg;
rand ireg_t ireg[1:16]; Indirect data register
rand uvm_reg_indirect_data uvm_ireg_1;
Abstract data
virtual function void build(); register container
uvm_reg r[$];
….
addr_reg = addr_reg_type::type_id::create("addr_reg");
uvm_ireg_1 = new("uvm_ireg_1", 32, UVM_NO_COVERAGE);
for(int x=1; x<=16; x++) begin
ireg[x] = ireg_t::type_id::create($psprintf(“ireg[%0d]", x));
ireg[x].build();
ireg[x].configure(this, null, $psprintf("ireg_hdl[%0d]", x));
r.push_back(ireg[x]);
end
addr_reg.build();
uvm_ireg_1.build();
addr_reg.configure(this, null, ""); Indirect addr and data registers

uvm_ireg_1.configure(addr_reg, r, this, null);


default_map.add_reg(addr_reg, 'h0, "RW");
default_map.add_reg(uvm_ireg_1, ‘h8, "RW");
….
endfunction
….
endclass

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

DUT reg_file Reads from addr:0x09


rd_data_reg will return this reg value
0x09 shr_ro_reg
wr_data_reg 0x09 shr_wo_reg Writes to addr:0x09
will update this register

50 Cadence Confidential
Shared Registers: SystemVerilog Code
// Defined with read-only access in IPXACT
class reg_RO extends uvm_reg;
`uvm_object_utils(reg_RO)
virtual function void build();
Define shared register like normal
F1 = uvm_reg_field::type_id::create("F1");
registers
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

51 Cadence Confidential
Shared Registers: SystemVerilog Code (cont)
// Register File
class block_B extends uvm_reg_block;
`uvm_object_utils(block_B)
rand reg_RO R;
rand reg_WO W;

virtual function void build();


default_map = create_map("", 0, 4, UVM_BIG_ENDIAN);
R = reg_RO::type_id::create("R");
R.configure(this, null, "R_reg");
R.build();
W = reg_WO::type_id::create("W");
W.configure(this, null, "W_reg");
W.build();
default_map.add_reg(R, 'h100, "R");
default_map.add_reg(W, 'h100, "W");
endfunction : build
endclass : block_B Shared register address offset

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

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
2 Normal register
class my_reg_Ra extends uvm_reg;
declaration
rand uvm_reg_field F1;
...
virtual function void build(); class my_blk extends uvm_reg_block;
rand my_reg_Ra Ra;
F1 = uvm_reg_field::type_id::create("F1");
F1.configure(this, 8, 0, "RW",rand my_reg_Rb
0, 8'h0, 1, 1, 1); Rb; 2 instances of register
endfunction virtual function build();
... default_map = create_map("", 0, 4, UVM_BIG_ENDIAN);
endclass Ra = reg_Ra::type_id::create("Ra",,get_full_name());
Ra.configure(this, null);
class my_reg_Rb extends uvm_reg;
uvm_reg_field F1; Ra.build();
... Rb = reg_Rb::type_id::create("Rb",,get_full_name());
virtual function void build(); Rb.configure(this, null);
Rb.build();
F1 = uvm_reg_field::type_id::create("F1"); Aliased register at
default_map.add_reg(Ra,
F1.configure(this, 8, 0, "RO", 0, 8'h0, 1, 0, 1); ‘h0100); additional address offsets
endfunction 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 The 3rd class definition in
endfunction next slide
Cadence Confidential
endclass
54
Aliased Register: SystemVerilog Code
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;
…… Aliasing function provided in 3rd class
function void configure(reg_Ra Ra, reg_Rb Rb); that link the 2 register type instance
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
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 Cadence Confidential
Lab DUT Introduction: UART DUT and Environment

Testbench Driving

RS
UART Module
rdb
Scoreboard uart_cover
(white box
coverage)

Monitor
UART DUT
APB txd
Tx FIFO Transmitter UART
sqr APB Mode sqr
Interface Switch rxd
Rx FIFO Receiver
mon drv mon drv

Control/Status Control/Interrupt
Registers Logic

Virtual Sequencer

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 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 Cadence Confidential
Lab 1 – Adding a Register to the XML File

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

div_val[7:0] Reset Value = 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; }

60 Cadence Confidential
Lab 1 – Generating the SystemVerilog Code

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.

End of Lab 1!

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 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 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 Cadence Confidential
Register Model instantiation and hook-up
Testbench
Module UVC Add the predictor component
Implement adapter Adapter Predictor to the module UVC
bus2reg and reg2bus object Component
tasks

Register APB Register Model


Sequencer master
seqr mon
Register Block
0x0000
memory

...
driver coll
(4K)
0x0FFF
Virtual 0x1000 mode0
Sequencer 0x1001 mode1
apb_if
dut 0x1002 mode2
0x1003 mode3
memctl 0x1010 status

mode0 mem_inst
mode1
memory Place register model, adapter,
mode2 32x4096
module UVC and register
mode3
sequencer in the testbench.
status
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 Cadence Confidential
Step 1: Transaction Adapter
class reg2apb_adapter extends uvm_reg_adapter;
Transaction Adapter
`uvm_object_utils(reg2apb_adapter)
function new(string name = "reg2apb_adapter");
super.new(name);
supports_byte_enables = 1; If bus protocol support byte lane enables
provides_responses = 1;
If bus driver returns responses
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; reg2bus function
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 Bus2reg function
rw.kind = apb.kind ? UVM_READ : UVM_WRITE;
rw.addr = apb.addr; rw.data = apb.data; rw.status = UVM_IS_OK;
endfunction
endclass
Cadence Confidential
67
Step 2: Testbench Activities
Testbench
Module UVC Add the predictor component
Implement register Adapter Predictor to the module UVC
sequencer and virtual object Component
sequencer

Register APB Register Model


Sequencer master
seqr mon
Register Block
0x0000
memory

...
driver coll
(4K)
0x0FFF
Virtual 0x1000 mode0
Sequencer 0x1001 mode1
apb_if
dut 0x1002 mode2
0x1003 mode3
memctl 0x1010 status

mode0 mem_inst
mode1
memory Place register model, adapter,
mode2 32x4096
module UVC and register
mode3
sequencer in the testbench.
status
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
Register model declaration
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 Transaction adapter declaration


`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 Cadence Confidential
Testbench Components build_phase() method
function new(input string name, input uvm_component parent=null);
super.new(name,parent);
endfunction
Register model build.
// class apb_uart_tb extends uvm_env … To enable reuse, first check if it’s
virtual function void build_phase(uvm_phase phase); build at higher level.
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();
Transaction adapter creation
end

reg2apb = reg_to_apb_adapter::type_id::create("reg2apb");
endfunction : build_phase

// Testbench code continued on the next slide…

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 Register sequence running
// . . . on APB bus sequencer
// UVM_REG Connections

reg_model.default_map.set_sequencer(apb0.master.sequencer, reg2apb);
……

endfunction : connect_phase

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 Cadence Confidential
Handling Reset - Example
class my_testbench extends uvm_env;
...
// Task to reset shadow register database
task reset_reg(); Detect hard reset
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
Forgetting the reset is a common hook up mistake
task run();
fork
reset_reg();
join_none

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 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 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 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 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 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

79 Cadence Confidential
End of Lab 2!
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

80 Cadence Confidential
End of Lab 2!
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 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 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 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.
* 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
Creating Sequences
class blk_seq extends uvm_reg_sequence;
The do actions are hidden with
`uvm_object_utils(blk_seq) read/write routines
Seq’s container
my_rf model; It is useful to combine positional
and named arguments binding
virtual task body();
Frontdoor Write
uvm_status_e status;
int data; Backdoor Write

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));
Backdoor Read
void'(model.randomize()); Memory frontdoor
endtask : body

endclass: blk_seq

While it is possible to mirror the shadow from sequences it is not


recommended (see on checking and monitoring)
85 Cadence Confidential
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

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

Start register sequencer on bus


sequencer

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 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 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 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 Cadence Confidential
End of Lab 3!
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 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 NO_HW_RESET_T
EST
their POR value.
uvm_reg_single_bit_bash_seq Sequentially walks ‘0’ and ‘1’, checking if NO_REG_BIT_BAS
H_TEST
uvm_reg_bit_bash_seq appropriately set or cleared.

uvm_[reg|mem]_single_access_seq Write frontdoor and read (checks) backdoor, later NO_[REG|MEM]_A


CCESS_TEST
uvm_[reg|mem]_access_seq writes backdoor and reads (checks) frontdoor.

uvm_mem_single_walk_seq Write a walking pattern into the memory then NO_MEM_WALK_T


EST
uvm_mem_walk_seq checks read back with the expected value.

uvm_[reg|mem]_shared_acc For each address map, writes the register | NO_SHARED_ACC


ESS_TEST
uvm_reg_mem_shared_access_seq memory via one map then confirms written by
ess_seq reading it from all other address maps.

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 Cadence Confidential
Built-in-sequences – Cadence Extension
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

Sequence body Registers Selection Filters


Register selection
happens here
setup get_all_registers using conditions

User hook post_setup get_configs using names

Sequence parameters
gets printed here print_configs filter_registers using addresses

Register rd/wr
happens here main using addr range

User hook post_main using string attributes

93 Cadence Confidential
Cadence’s Built-in Sequences
Built-in-sequence Description Skip attribute
Reads all of the register in a block. It is assumed that
uvm_reg_built_in_read_all_regs_seq explicit monitor does register value checking NO_RD_REG_TESTS

This sequence is going to write all registers with


uvm_reg_built_in_write_all_regs_seq random value. Sequence has a flag to direct the value NO_WR_REG_TESTS
to be specific value, than random.
This sequence is going to first write register and then
NO_RD_REG_TESTS
immediately read that register. For writing, sequence
uvm_reg_built_in_wr_follow_rd_seq or
has a flag to direct the value to be specific value, than NO_WR_REG_TESTS
random.
It writes a random value to a register and reads all the
NO_RD_REG_TESTS
other registers to make sure the write did not affect
uvm_reg_built_in_aliasing_seq or
them. It does this for each and every register in the NO_WR_REG_TESTS
block
This sequence can be used to generate access file for
uvm_reg_generate_access_file_seq backdoor access optimization

This sequence is going to call all built-in-sequences


one-by-one for a container Individual skip
uvm_reg_built_in_all_seq
attributes

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 Cadence Confidential
Registers’ Checking and Coverage

• 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

96 Cadence Confidential
Monitoring and Checking in the Stimuli
Implicit Predictor
• 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).
97 Cadence Confidential
The Recommended approach:
Explicit Predictor
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

Predictor

Map reg.predict(data)
addr no
Compare
data If yes
Adapter read
With
shadow

Bus UVC

Monitor Bus

Sequencer Driver

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 Predictor Component
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 … Create predictor and adapter


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 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 Connect address map
// . . . and adapter to predictor
// 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

When bus transfer is


observed
pass it to predictor

100 Cadence Confidential


Using the Shadow Register Model for Checking

• 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

101 Cadence Confidential


Interrupt Example
Testbench

A set of routines exist


rdb UART Module to modify register values
uart_cover
(white box
int coverage)

status
interrupt
UART DUT // within the monitor
Tx FIFO Transmitter
virtual task update_reg_model();
APB Mode forever begin
Interface Switch @interrupt;
Rx FIFO Receiver
set_reg_val_by_name(“csr.interrupt”, 1);
end
Control/Status Control/Interrupt endtask: update_reg_model
Registers Logic

102 Cadence Confidential


Predefined Register Coverage
• IP-XACT allows enabling coverage for desired fields
<vendorExtensions:collect_coverage>cov_all</vendorExtensions:collect_coverage>
class control_reg_c extends uvm_reg;

covergroup wr_cg;
option.per_instance=1;
div_val : coverpoint ctrl.value[1:0]; Enabled fields are added as coverage
endgroup points
covergroup rd_cg;
option.per_instance=1;
div_val : coverpoint ctrl.value[1:0];
endgroup Extend virtual methods

virtual function void sample(uvm_reg_data_t data, byte_en, bit is_read, uvm_reg_map map);
super.sample(data, byte_en, is_read, map);
if(!is_read) wr_cg.sample();
if(is_read) rd_cg.sample();
endfunction
endclass : control_reg_c

Cadence Confidential
103
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 Note that you must use a
different coverage group name
function void sample();
super.sample();
cross_control_cg.sample();
endfunction
endclass

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 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 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

107 Cadence Confidential


End of Lab 4!
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 Cadence Confidential


Cadence Register Viewer - iregViewer

• 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

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 Cadence Confidential


The Register Viewer - iregViewer

111 Cadence Confidential


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 - 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
112 Cadence Confidential

Das könnte Ihnen auch gefallen