Вы находитесь на странице: 1из 224

System Verification

Methodology (sVM) Developer


Manual
Version 2.0 Beta 1

Legal Notice
Copyright 2004-2005 Verisity Design, Inc. All rights reserved. Verisity was acquired by
Cadence Design Systems, Inc. in 2005.

Trademarks
Verisity, the Verisity logo, eAnalyzer, eCelerator, eRM, Invisible Specman, LicenseE,
Pure IP, Specman, Specman Elite, SpeXsim, SpeXtreme, SureCov, SureLint, SureSolve,
sVM, Verification Advisor, Verification Alliance, Verification Vault, Verification
Viewport, Visualization Toolkit, vManager, vPlan, Xbench, Xchange, Xcite, XoC, Xpert,
Xsim, and Xtreme are either trademarks or registered trademarks of Verisity Design, Inc.
in the United States and/or other jurisdictions. All other trademarks are the exclusive
property of their respective owners.

Confidentiality Notice
Verisity confidential; do not distribute. The contents of this document constitute valuable
proprietary and confidential property of Verisity Design, Inc. No part of this information
product may be reproduced, transmitted, or translated in any form or by any means,
electronic, mechanical, manual, optical, or otherwise without prior written permission
from Verisity Design, Inc.
Information in this product is subject to change without notice and does not represent a
commitment on the part of Verisity. The information contained herein is the proprietary
and confidential information of Verisity or its licensors, and is supplied subject to, and may
be used only by Verisitys customers in accordance with, a written agreement between
Verisity and its customers. Except as may be explicitly set forth in such agreement,
Verisity does not make, and expressly disclaims, any representations or warranties as to the
completeness, accuracy, or usefulness of the information contained in this document.
Verisity does not warrant that use of such information will not infringe any third party
rights, nor does Verisity assume any liability for damages or costs of any kind that may
result from use of such information.

Restricted Rights Legend


Use, duplication, or disclosure by the Government is subject to restrictions as set forth in
subparagraphs (c)(1)(ii) of the Rights in Technical Data and Computer Software clause at
DFARS 252.227-7013.

Destination Control Statement


All technical data contained in this product is subject to the export control laws of the
United States of America. Disclosure to nationals of other countries contrary to United
States law is prohibited. It is the readers responsibility to determine the applicable
regulations and to comply with them.

Contents

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1-1
1.1
1.2
1.3
1.4

About This Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-1


About the sVM Release Library (svm_lib) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-2
The sVM Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-3
1.3.1
Terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-4
Visual Conventions in This Manual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-5

Introduction to SoC Verification . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-1


2.1

2.2

Preface
2.1.1
2.1.2
2.1.3
2.1.4

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-1
Why SoC Verification Is Different . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-1
What This Document Tries to Do . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-2
What Is in This Document? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-2
What Is an SoC? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-2
2.1.4.1 Not Everything Is an SoC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-3
2.1.4.2 SoCs Are Similar to the Corresponding Board-Level Systems . . . . . 2-3
2.1.5
Our Example: The RSoC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-3
2.1.5.1 Some Typical Specifications for the Various Sub-DUTs . . . . . . . . . 2-5
The RSoC HW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-6
2.2.1
The CPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-7
2.2.2
The CPU Bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-7
2.2.3
Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-7
2.2.4
The Bridge to the System Bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-8
2.2.5
The Peripheral Controllers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-8

System Verification Methodology

Version 2.0 Beta 1

iii

Contents

2.2.6
2.2.7
2.2.8
2.2.9
2.2.10

2.3

2.4

From Module Level to System Level . . . . . . . . . . . . . . . . . . . . . . . .3-1


3.1

3.2

iv

Registers and the Magic of Memory-Mapped IO . . . . . . . . . . . . . . . . . . . . . . 2-8


The DMA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-9
Variations on a Theme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-9
What Does SoC HW Verification Mean? . . . . . . . . . . . . . . . . . . . . . . . . . . 2-10
Typical SoC Bugs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-10
2.2.10.1 Bugs in New Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-10
2.2.10.2 Wrong Assumptions about Some Module . . . . . . . . . . . . . . . . . . . . 2-11
2.2.10.3 Bad Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-11
2.2.10.4 Badly Wired Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-11
2.2.10.5 Problems Arising from the Interaction of Modules . . . . . . . . . . . . . 2-11
Verifying the SoC HW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-11
2.3.1
Verifying the XCore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-12
2.3.2
Verifying the Full RSoC Hardware Environment . . . . . . . . . . . . . . . . . . . . . 2-12
2.3.2.1 Yank Out the CPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-13
2.3.2.2 Create a Family of Bus Sequences Emulating the Software . . . . . . 2-13
2.3.2.3 Controlling the Other Side . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-14
2.3.3
Checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-14
2.3.4
Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-15
Verifying the HW with the SW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-16
2.4.1
Verifying the HW with the SW Device Drivers . . . . . . . . . . . . . . . . . . . . . . 2-17
2.4.1.1 Via Method Ports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-18
2.4.1.2 Create and Load Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-18
2.4.1.3 Create an Interpreter for Read/Write Requests . . . . . . . . . . . . . . . . 2-19
2.4.1.4 Seamless and Such . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-19
2.4.1.5 CVL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-19
2.4.2
Verifying the Hardware with the Application Software . . . . . . . . . . . . . . . . 2-19

System eVCs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-3


3.1.1
Verifying Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-3
3.1.2
Structure and Functionality of System eVCs . . . . . . . . . . . . . . . . . . . . . . . . . . 3-4
3.1.3
System eVC Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-5
Module and System eVC Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-6
3.2.1
Module eVC Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-7
3.2.2
System eVC Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-8
3.2.3
System eVC Monitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-8
3.2.3.1 Connecting the Monitor with Pointers . . . . . . . . . . . . . . . . . . . . . . . . 3-9
3.2.3.2 Connecting the Monitor with Ports . . . . . . . . . . . . . . . . . . . . . . . . . 3-10
3.2.3.3 System eVC Monitor Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-11

Version 2.0 Beta 1

System Verification Methodology

Contents

3.3

3.4

3.5

3.6

3.7
3.8

3.2.4
Stand-In Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-12
3.2.5
Reference Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-14
Integrating eVCs into an SVE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-15
3.3.1
Connecting eVCs with Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-16
3.3.2
Recent Improvements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-17
Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-17
3.4.1
Configuration Struct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-19
3.4.2
Configuration with Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-19
3.4.3
Extending Subtypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-19
3.4.4
Defining Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-20
3.4.5
SVE Configuration File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-20
Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-21
3.5.1
Reusing Sequence Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-21
3.5.2
Reusing Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-21
3.5.3
Sequences: Module to System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-22
3.5.4
Reuse of Register Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-22
3.5.5
Organizing and Using Sequence Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-23
Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-23
3.6.1
Module eVC Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-24
3.6.2
System-Level Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-24
3.6.3
Reusing Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-24
3.6.4
Adding Coverage Definitions to System eVCs . . . . . . . . . . . . . . . . . . . . . . . 3-25
Checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-26
3.7.1
Connecting the Scoreboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-26
Scalability Issues in System Verification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-27
3.8.1
Stimulus Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-28
3.8.1.1 Sequence Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-28
3.8.1.2 Generation Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-29
3.8.2
Checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-32
3.8.2.1 Preparing the eVC for Scalability . . . . . . . . . . . . . . . . . . . . . . . . . . 3-32
3.8.2.2 Grouping Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-32
3.8.2.3 Determining the Appropriate Tradeoff . . . . . . . . . . . . . . . . . . . . . . 3-33
3.8.3
Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-33
3.8.3.1 Grouping Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-33
3.8.3.2 Determining the Appropriate Tradeoff . . . . . . . . . . . . . . . . . . . . . . 3-34
3.8.3.3 Minimizing Overhead with the Coverage API . . . . . . . . . . . . . . . . 3-34
3.8.4
Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-34
3.8.5
eVC-specific Solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-34

System Verification Methodology

Version 2.0 Beta 1

Contents

3.8.5.1
3.8.5.2
3.8.5.3
3.8.5.4

The Register and Memory Model . . . . . . . . . . . . . . . . . . . . . . . . . . .4-1


4.1

4.2
4.3

4.4

4.5

4.6

vi

Minimizing Context Switching . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-35


Sharing Monitors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-35
Implementing Deterministic Behavior . . . . . . . . . . . . . . . . . . . . . . . 3-35
Optimizing Sequence Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-35

Introduction to the Register and Memory Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-1


4.1.1
Main Features of the Register and Memory Package . . . . . . . . . . . . . . . . . . . 4-2
4.1.2
Naming Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-2
4.1.3
Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-2
Overview of the Register and Memory Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-2
Architecture of the Register Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-7
4.3.1
Defining the Register Address and Data Width . . . . . . . . . . . . . . . . . . . . . . . . 4-8
4.3.2
Defining a Register File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-9
4.3.3
Defining Registers with the reg_def Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-9
4.3.3.1 reg_def Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-10
4.3.3.2 Defining a Register Instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-11
4.3.3.3 Defining Multiple Instances of a Register Type . . . . . . . . . . . . . . . 4-12
4.3.3.4 reg_list Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-13
4.3.3.5 Mirroring Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-13
4.3.3.6 Defining Coverage of Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-14
4.3.4
Instantiating the Register File in the Architecture . . . . . . . . . . . . . . . . . . . . . 4-15
4.3.5
Instantiating the Address Map and the RSD . . . . . . . . . . . . . . . . . . . . . . . . . 4-15
4.3.6
Adding the Register File to the Address Map . . . . . . . . . . . . . . . . . . . . . . . . 4-15
4.3.6.1 Mirroring Register Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-16
Integration of the Register Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-17
4.4.1
Integrating the RSD with the BFM Sequence Driver . . . . . . . . . . . . . . . . . . 4-18
4.4.2
Updating the Register Model Using an eVC Monitor . . . . . . . . . . . . . . . . . . 4-20
Creating Register Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-21
4.5.1
Basic Register Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-21
4.5.2
write_reg and read_reg Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-24
4.5.3
Creating Deterministic Configuration Sequences . . . . . . . . . . . . . . . . . . . . . 4-25
4.5.4
Modifying a Register Field . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-26
4.5.5
Writing to a Specific Instance of a Register Type . . . . . . . . . . . . . . . . . . . . . 4-27
4.5.6
Accessing Random Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-28
4.5.6.1 Accessing a Random Register . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-29
4.5.6.2 Accessing Entire Register Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-30
Using the Register Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-30
4.6.1
Implementing Side Effects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-31
Version 2.0 Beta 1

System Verification Methodology

Contents

4.6.2
4.6.3

4.7

4.8

Reset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-33
Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-33
4.6.3.1 Coverage of Register Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-33
4.6.3.2 Adding or Modifying Coverage Definitions . . . . . . . . . . . . . . . . . . 4-34
4.6.3.3 Customizing Coverage Sampling . . . . . . . . . . . . . . . . . . . . . . . . . . 4-35
4.6.4
Backdoor Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-36
4.6.4.1 Setting the HDL Path of a Register . . . . . . . . . . . . . . . . . . . . . . . . . 4-36
4.6.4.2 Backdoor Accessing of Registers . . . . . . . . . . . . . . . . . . . . . . . . . . 4-36
4.6.4.3 Monitoring Internal Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-38
4.6.4.4 Overriding the Default Backdoor Implementation . . . . . . . . . . . . . 4-38
4.6.4.5 Backdoor Accesses and Update of the Address Map . . . . . . . . . . . 4-39
4.6.4.6 Backdoor-Related Fields and Methods . . . . . . . . . . . . . . . . . . . . . . 4-39
4.6.5
Indirect Addressing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-40
4.6.5.1 Driving Indirect Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-41
4.6.5.2 Identifying and Handling Indirect Access . . . . . . . . . . . . . . . . . . . . 4-43
4.6.6
Changing the Register Field Order . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-44
4.6.7
Customizing Addressing Width . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-45
4.6.8
Register Sequences and End of Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-46
4.6.9
Controlling Message Verbosity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-46
4.6.10 Accessing Multiple Address Maps on the Bus . . . . . . . . . . . . . . . . . . . . . . . . 4-47
4.6.11 Disabling Comparison for Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-48
4.6.12 Register Field Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-49
Sparse Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-50
4.7.1
Instantiating a Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-51
4.7.2
Accessing Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-51
4.7.2.1 write_mem and read_mem Macros . . . . . . . . . . . . . . . . . . . . . . . . . 4-52
4.7.3
Updating the Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-53
4.7.4
Memory Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-53
4.7.4.1 Reading from and Writing to a File . . . . . . . . . . . . . . . . . . . . . . . . . 4-54
4.7.4.2 Controlling Returned Data of Uninitialized Addresses . . . . . . . . . . 4-54
4.7.4.3 Side Effects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-55
4.7.4.4 Memory Backdoor Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-56
4.7.5
Storing Complex Structures in Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-57
4.7.5.1 Creating Memory Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-57
4.7.5.2 Connecting Memory Objects to the Memory . . . . . . . . . . . . . . . . . 4-58
4.7.6
Accessing Objects in Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-60
4.7.6.1 write_mem_obj and read_mem_obj Macros . . . . . . . . . . . . . . . . . . 4-60
4.7.6.2 Methods for Accessing Objects in Memory . . . . . . . . . . . . . . . . . . 4-61
Register and Memory Data Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-61
4.8.1
Type Naming Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-62

System Verification Methodology

Version 2.0 Beta 1

vii

Contents

4.8.2
4.8.3
4.8.4
4.8.5

4.9

viii

Type Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-62


Register Attribute Structs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-63
vr_ad_operation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-64
vr_ad_reg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-64
4.8.5.1 write_reg_val() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-65
4.8.5.2 read_reg_val() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-66
4.8.5.3 write_reg_raw() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-66
4.8.5.4 write_reg_rawval() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-67
4.8.5.5 set_static_info() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-68
4.8.5.6 set_write_mask() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-69
4.8.5.7 set_read_mask() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-70
4.8.5.8 set_compare_mask() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-71
4.8.5.9 set_backdoor_path() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-71
4.8.5.10 set_field_backdoor_path() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-72
4.8.5.11 update() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-73
4.8.5.12 compare_and_update() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-74
4.8.5.13 post_access() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-75
4.8.5.14 Fields and Methods of vr_ad_reg . . . . . . . . . . . . . . . . . . . . . . . . . . 4-75
4.8.6
vr_ad_reg_static_info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-77
4.8.7
vr_ad_reg_file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-78
4.8.7.1 add_with_offset() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-79
4.8.7.2 Fields and Methods of vr_ad_reg_file . . . . . . . . . . . . . . . . . . . . . . . 4-80
4.8.8
vr_ad_map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-82
4.8.8.1 add_with_offset() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-83
4.8.8.2 add_to_addr_map() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-84
4.8.8.3 add_unmapped_item() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-85
4.8.8.4 update() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-85
4.8.8.5 fetch() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-86
4.8.8.6 compare_and_update() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-87
4.8.8.7 Fields and Methods of vr_ad_map . . . . . . . . . . . . . . . . . . . . . . . . . . 4-88
4.8.9
vr_ad_mem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-91
4.8.9.1 readmemh() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-91
4.8.9.2 dumpmemh() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-92
4.8.9.3 get_data() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-93
4.8.10 vr_ad_sequence_driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-95
4.8.10.1 Fields and Methods of vr_ad_sequence_driver . . . . . . . . . . . . . . . . 4-95
Address Management (Sets) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-96
4.9.1
add_segment() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-98
4.9.2
alloc_from_set() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-99
4.9.3
dealloc_to_set() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-100
4.9.4
lock_item() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-101
Version 2.0 Beta 1

System Verification Methodology

Contents

4.9.5
release_item() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-102
4.9.6
Memory-Management Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-102
4.10 Registers Visualization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-104
4.10.1 All Address Maps Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-105
4.10.2 Top-Level Address Map Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-105
4.10.3 Detailed Address Map Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-106
4.10.4 Register Files Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-107
4.10.5 Address Sets Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-108
4.10.6 Register File Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-108
4.10.7 Stripe Chart Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-109
4.11 Register and Memory Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-110
4.11.1 show map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-111
4.11.2 trace ad alloc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-111

TLM Verification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5-1


5.1
5.2
5.3

5.4
5.5
5.6
5.7

5.8
5.9

Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-1
TLM System eVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-2
TLM Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-3
5.3.1
TLM Wrapper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-3
5.3.2
TLM BFM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-3
5.3.3
TLM Monitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-4
Interfacing with SystemC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-6
Configuration for Working with SystemC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-6
Modifying the SystemC Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-7
Open TLM Verification Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-9
5.7.1
TLM BFM Methodology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-9
5.7.2
TLM Monitor Methodology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-10
5.7.3
Multiple Instances of Input Method Ports . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-13
5.7.4
Method Port Location . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-14
5.7.5
PV Mode Synchronization Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-14
5.7.6
Multi-Level Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-15
5.7.6.1 Multiple Bus Monitors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-15
5.7.6.2 Independent Agents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-15
5.7.6.3 Bridge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-15
The XBus TLM Demo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-16
The XCore TLM Demo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-18

System Verification Methodology

Version 2.0 Beta 1

ix

Contents

Hardware-Software Co-Verification . . . . . . . . . . . . . . . . . . . . . . . . .6-1


6.1
6.2
6.3
6.4
6.5

Standardization Using sVM Compliance Checks . . . . . . . . . . . . . .7-1


7.1
7.2
7.3
7.4
7.5
7.6
7.7

Architecture of Software eVCs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-2


Ports for Software eVCs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-3
BFMs for Software eVCs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-4
Sequences for Software eVCs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-4
The Monitor of the Software eVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-6

Packaging and Name Space Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-2


Architecture Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-2
Registers and Memory Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-3
Checking Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-4
Coverage Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-4
Sequences Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-5
Hardware-Software Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-5

Version 2.0 Beta 1

System Verification Methodology

Introduction

This chapter includes a general introduction to System Verification Methodology (sVM) and to this
manual. It contains the following sections:

About This Book on page 1-1


About the sVM Release Library (svm_lib) on page 1-2
The sVM Library on page 1-3
Visual Conventions in This Manual on page 1-5

1.1

About This Book

This manual is all about verification for System-on-a-Chip (SoC). System Verification Methodology
(sVM) defines how to verify systems. System verification deals with many different aspects of
verification, such as:

Module-to-system integration
Register and memory modeling
Hardware-software co-verification
Transaction-level modeling (TLM) and verification
Post-silicon verification
This books intended audience includes eVC developers, verification environment developers, and
technical managers responsible for these environments.
sVM is currently a beta release. It describes the best-known practice for system verification based on
Specman Elite version 5.0 and eRM 2.1.

System Verification Methodology

Version 2.0 Beta 1

1-1

Introduction
About the sVM Release Library (svm_lib)

The following fundamental methodological issues are not finalized yet:

Scoreboard methodology using one to many method ports


Software interface using GSA (generic software adaptor)
Following is a brief description of each chapter in this manual.
Chapter 1 Introduction

This chapter

Chapter 2 Introduction to SoC Verification

A light introduction to the various aspects of


system verification

Chapter 3 From Module Level to System Level How to construct a system verification

environment out of other verification


components
Chapter 4 The Register and Memory Model

How to model registers and memory in a system


verification environment

Chapter 5 TLM Verification

How to use transaction-level modeling for


system verification

Chapter 6 Hardware-Software Co-Verification

How to do co-verification of hardware and


software

Chapter 7 Standardization Using sVM


Compliance Checks

Requirements for developing a uniform and


high-standard eVC

1.2

About the sVM Release Library (svm_lib)

The sVM library (svm_lib) contains all of the deliverables associated with sVMinfrastructure
utilities, examples, documentation, and more.
The library includes the following packages and subdirectories:
svm_util

1-2

This package includes the infrastructure syntax, types, and utilities needed
for writing eVCs. It is the core module of the sVM Library.

Version 2.0 Beta 1

System Verification Methodology

Introduction
The sVM Library

Documents
(in the svm_docs
directory)

This directory contains all of the main sVM documentation. It also contains
sVM presentations in PDF format.

Golden eVCs

These are example eVC packages, used to demonstrate modularity and reuse
of verification environments. For more information, see:

XCore eVC User Guide (svm_lib/vr_xcore/docs/vr_xcore_evc.pdf)


QSoC eVC User Guide (svm_lib/vr_qsoc/docs/vr_qsoc_evc.pdf)
Example
directories

These are minipackages that demonstrate use of some specific features


provided by the sVM library like sequences and packaging. They all have an
ex_ prefix (for example, ex_gsa).

Each of these packages and subdirectories contains its own PACKAGE_README.txt or README.txt
file, giving details on the content.

1.3

The sVM Library

The svm_lib has several examples of DUTs, eVCs, and SVEs (Simulation and Verification
Environments). They demonstrate the development of verification environments from module to system
level. Each higher level eVC reuses the lower level eVCs. Each eVC has a sample SVE, demonstrating
how the eVC can be integrated into the system verification environment.
The sVM library contains:
Registers and
Memory package

Generic verification component (eVC) for modeling registers and memory.

GSA

Generic software adaptor for integrating with software.

XCore eVC

Verification environment for a module that connects an XSerial port to the


XBus.

XSerial_TLM eVC Verification environment for a TLM serial interface. (This extends the XSerial
eVC in the eRM library.)
XBus_TLM eVC

Verification environment for a TLM bus. (This extends the XBus eVC in the
eRM library.)

QSoC eVC

Verification environment for a system built of two XCore modules on the same
XBus.

QSoC_SW eVC

Verification environment for the software component of the QSoC

System Verification Methodology

Version 2.0 Beta 1

1-3

Introduction
Terminology

QSoC_d eVC

Verification environment for a system built from a QSoC and a software driver
(driving its registers).

XBridge eVC

Verification environment for a simple AHB to XBus bridge.

RSoC eVC

Verification environment for a system constructed from a QSoC_d eVC with a


software application running on top of it.

Note Some of the examples are not fully developed and documented.

See Also
XCore eVC User Guide (svm_lib/vr_xcore/docs/vr_xcore_evc.pdf)
QSoC eVC User Guide (svm_lib/vr_qsoc/docs/vr_qsoc_evc.pdf)

1.3.1

Terminology

Table 1-1

sVM Terminology

Term

Explanation

eVC

An e Verification Component. It is a ready-to-use, out-of-the-box verification


environment, typically focusing on a specific protocol or architecture (such as
Ethernet, AHB, PCI).

eRM

e Reuse Methodology. For more information, see the e Reuse Methodology


(eRM) Developer Manual.

SVE

Simulation and Verification Environment. A verification environment for a


specific device in a specific configuration. It contains an HDL module, an eVC,
at least one file that configures the eVC for the SVE, and several test files.

RSD

Register Sequence Driver. A dedicated sequence driver for register operations.


For more information, see Chapter 4 The Register and Memory Model.

VSD

Virtual Sequence Driver. For more information, see Chapter 5 Sequences:


Constructing Test Scenarios in the e Reuse Methodology (eRM) Developer
Manual.

Interface eVC

An eVC for checking an interface. Usually it is used to verify a protocol, for


example, vr_ahb for verifying the AHB protocol.

Module eVC

An eVC for checking a module. Usually it is integrated with at least one interface
eVC, as all modules have at least one interface.

1-4

Version 2.0 Beta 1

System Verification Methodology

Introduction
Visual Conventions in This Manual

Table 1-1

sVM Terminology (continued)

Term

Explanation

System eVC

An eVC for checking a system, typically an SoC. It includes several module and
interface eVCs.

External eVC

An interface eVC for checking an interface that is external to the device. A


typical example is a serial interface, for example, Ethernet. A bus can also be
external if it is assumed that other devices can share this same bus.

Internal eVC

Either a module eVC, a System eVC, or an interface eVC that verifies an internal
component of the device.

1.4

Visual Conventions in This Manual

This manual uses visual cues to help you locate and interpret information easily. These cues are
explained in Table 1-2.
Table 1-2

Document Conventions

Visual Cue

Represents

courier font

Indicates code. For example:


do burst_response keeping {

courier bold

Used to highlight important sections of code, like actions. For example:


do burst_response keeping {

bold

The bold font indicates Specman Elite keywords in descriptive text. For
example, the following sentence contains keywords for the show ini
command and the get_symbol() routine:
You can display these settings with the show ini setting command or
retrieve them within e code with the get_symbol() routine.

italic

The italic font represents user-defined variables that you must provide.
For example, the following line instructs you to type the write cover as
it appears, and then the actual name of a file:
write cover filename

System Verification Methodology

Version 2.0 Beta 1

1-5

Introduction
Visual Conventions in This Manual

Table 1-2

Document Conventions (continued)

Visual Cue

Represents

[ ] square brackets

Square brackets indicate optional parameters. For example, in the


following construct the keywords list of are optional:
var name: [list of] type

[ ] bold brackets

Bold square brackets are required. For example, in the following construct
you must type the bold square brackets as they appear:
extend enum-type-name: [name,]

construct,

An item, followed by a separator (usually a comma or a semicolon) and an


ellipsis is an abbreviation for a list of elements of the specified type. For
example, the following line means you can type a list of zero or more
names separated by commas.
extend enum-type-name: [name,]

The pipe character indicates alternative syntax or parameters. For


example, the following line indicates that either the bits or bytes keyword
should be used:
type scalar-type (bits | bytes: num)

cmd-prompt

Denotes the prompt for the Cadence tool you are running, including
Specman Elite, vManager, SpeXsim, or SpeXtreme.

C1>, C2>,

Denotes the SpeXsim prompt (VHDL, Verilog or mixed-HDL designs).


Also denotes a third-party Verilog simulator prompt.

>

Denotes a third-party VHDL simulator prompt.

Denotes the UNIX prompt.

1-6

Version 2.0 Beta 1

System Verification Methodology

Introduction to SoC Verification

by Yoav Hollander

2.1

Preface

This document is a light introduction to SoC verification.


Throughout this introduction we follow the example of the RSoC (the Representative SoC),
pretending that there is one simple solution to each problem.
This should serve as a light introduction to the sVM cookbook, a heavyweight document which quickly
dispels the notion that there is a single answer to any question in this area.
But for now relax and enjoy the ride.

2.1.1

Why SoC Verification Is Different

You are a Specman user, and you know how to write, say, a protocol eVC. Easy, right? Start with an env
unit, put in it a few agent units with each one having a BFM and a sequence driver, write some monitors,
checkers, and coverage, add a touch of cinnamon and you are done.
OK, it may be a little more involved than that, but you get my drift.
But an SoC is a horse of a different color. Look at a block diagram and you get a little dizzy. Where do
you start? And there is a CPU involved, so probably well need to go into HW/SW co-verification.
Looks complex.
Relax. This document will tell you the basics.

System Verification Methodology

Version 2.0 Beta 1

2-1

Introduction to SoC Verification


What This Document Tries to Do

2.1.2

What This Document Tries to Do

It will explain what a typical SoC looks like.


It will explain why an SoC is a challenge to verify. This is not necessarily bad. Using Specman and
the knowledge gleaned from this document, you may become the only person around who can do
this tough job. Get ready to become a local hero.

It will tell you what it means to verify such a creature: what is a typical test, what are the data structures
for generation, how to do checking, what is interesting to cover, etc.

It will discuss the relation to module and protocol eVCs. SoCs are often constructed from mostly
pre-verified modules. How do you write the eVCs for the modules, and how do you reuse them for
the whole? An interesting question, and it even has an answer.

Finally, it will discuss (briefly) the issue of HW/SW co-verification.


Notes

This document contains no e code.


This document assumes that you know eRM and that all you need is just the above stuff.
While this document tries to set some generic guidelines, every SoC design is different, and you must
be sure you understand the specific DUT at hand before dispensing advice. In fact, one of the golden
rules of verification (and of psychotherapy in general) is: If you are not a good listener, get another
job.

2.1.3

What Is in This Document?

Preface on page 2-1

Gives an example of a typical SoC.

The RSoC HW on page 2-6

Describes the SoC HW and its typical bugs.

Verifying the SoC HW on page 2-11

Discusses how to verify the HW.

Verifying the HW with the SW on page 2-16

Takes a brief look at verifying the HW with the SW.


As you might expect, though, generalizing advice is
hard: it really depends on what the thing does.

So lets move on. What is an SoC?

2.1.4

What Is an SoC?

SoCs come in many shapes and forms. In fact:

2-2

Version 2.0 Beta 1

System Verification Methodology

Introduction to SoC Verification


Our Example: The RSoC

SoC is an implementation technology, not a market segment.


I forget who first coined this immortal sentence. It means that an SoC could be the heart of a medical
device, a comm device, a graphics device and many other things. Do not let that scare you thoughthe
various SoC designs are similar enough that the advice in this document will be good for most of them.It
is the SW running them, and the peripherals connected to them, that make them suddenly control your
cell phone, your pacemaker, your guided missile.
So, what is in this document?

2.1.4.1

Not Everything Is an SoC

SoC has become a trendy term. Everyones products are suddenly especially designed for SoC. In
fact, 56% of all trade journal articles now start like this:
1.

A reference to Moores Law

2.

Thus, SoCs are getting harder to design and verify.

3.

So, buy our new color monitors: They are bigger and have more colors in themjust right for SoC
design!

With this comes a more tolerant definition of SoC, namely a chip with lots of things in it. We are
going to use a somewhat more restrictive definition of an SoC (see below).

2.1.4.2

SoCs Are Similar to the Corresponding Board-Level Systems

While an SoC with n components is harder to verify than a board with the same n components, many of
the same lessons apply.
The main differences, by the way, are:

SoCs have a higher cost of failure.


It is harder to debug them in pieces (especially post-silicon).

2.1.5

Our Example: The RSoC

Let us now take a look at our representative SoC, the RSoC.

System Verification Methodology

Version 2.0 Beta 1

2-3

Introduction to SoC Verification


Our Example: The RSoC

Figure 2-1

Point of Sale

Let us start with the big picture: The RSoC you are about to verify is at the heart of a supermarket point
of sale (Figure 2-1). You need to verify the full (HW+SW) RSoC, just to keep the customers smiling.
Figure 2-2

2-4

Full RSoC

Version 2.0 Beta 1

System Verification Methodology

Introduction to SoC Verification


Our Example: The RSoC

Figure 2-2 is a block diagram of the full RSoC. The full DUT to be verified contains the hardware, the

low-level (software) device drivers, and the complex supermarket point-of-sale application program.
In addition to the full RSoC, we should verify at least two additional sub-DUTs:

The full RSoC chip


The RSoC chip + the device drivers
The RSoC hardware has two serial interfaces, a USB interface and an Ethernet interface. We also need
to verify separately the serial (XCore) module and the Ethernet module, because they are new.
I consider myself an expert on the subject, having stood in countless checkout lines. However, I have
never actually pried open any of those machines, so I could be way off. Nevertheless, let us assume:

After reset, the RSoC accesses the central supermarket database via Ethernet, reading in crucial
updates such as the ever-changing price of onion.

Then, as the checkout clerk processes the next person in line, the RSoC gets barcode readings and
credit-card swipe information through the USB. Through one serial interface, it gets key clicks from
the cash register. Through another serial interface, it communicates via Ethernet with the central
credit-card validation system and sends output to the screen.
Note Things like the barcode reader are outside of the DUT.

2.1.5.1

Some Typical Specifications for the Various Sub-DUTs

Lets consider some examples of what should be checked in the various sub-DUTs.
An RSoC_HW check Corrupt packets should cause an interrupt
Check that whenever the Ethernet controller receives a corrupt packet from the outside world, it
interrupts the CPU.
A typical input scenario for this level is:
1.

Program the Ethernet registers for receive.

2.

Receive a bad packet from the Ethernet port.

System Verification Methodology

Version 2.0 Beta 1

2-5

Introduction to SoC Verification


The RSoC HW

An RSoC_D check Corrupt packets should cause a retransmit request


Check that whenever the system receives a corrupt packet from the outside world, it sends a
corresponding retransmit request. It should keep doing that until the buffer is fully transmitted.
Note This is implemented in software in the device driver, in response to the interrupt mentioned
above. Thus, a DUT error here could be caused either by a SW bug or by the HW not satisfying the
aforementioned check.
A typical scenario at this level is:
1.

Call the driver C routine enet_send_buffer().

2.

Receive a bad packet from the Ethernet port

An RSoC_Full check Never accept a bad credit card


Assume that the full RSoC gets the following multi-channel input sequence
<scan-carrots> <scan-milk> <total> <swipe-credit-card>
<receive-bad-credit-response> <receive-corrupted-packet> <total>

and it suddenly accepts the bad credit card.


The logic for rejecting credit cards when the credit server sends a bad-credit response is implemented
in the application software. However, that software depends on the device driver working correctly,
and that in turn depends on the hardware working correctly.
Our job, of course, is to make sure that no such nonmail.barak-online.netsense happens. Well start with
the innermost sub-DUT, namely the hardware.

2.2

The RSoC HW

Figure 2-3 shows the RSoC hardware.

2-6

Version 2.0 Beta 1

System Verification Methodology

Introduction to SoC Verification


The CPU

Figure 2-3

RSoC Hardware

It represents a fairly typical (though somewhat simple) SoC, with all of the right ingredients. See below
for some possible variants.
Notes

If you are already familiar with what an SoC looks like inside, you can just skim through the following
description.

Many of the following ingredients (for example, the CPU and some of the peripheral controllers) can
be pre-existing, pre-verified modules.

2.2.1

The CPU

At the top there is the CPU, controlling it all. We always try to put the CPU on top, so we can later draw
the SW above it. If you see this drawn differently on a whiteboard, try rotating the whiteboard.
Without loss of generality, we will assume that the CPU is an ARM.

2.2.2

The CPU Bus

The CPU sits on the CPU bus. In our example, this will be the AHB.

2.2.3

Memory

On the same bus there is a boot ROM (for instructions) and a RAM (for instructions and data). For
simplicity we show a single Memory block in the Figure 2-3.

System Verification Methodology

Version 2.0 Beta 1

2-7

Introduction to SoC Verification


The Bridge to the System Bus

2.2.4

The Bridge to the System Bus

On the fast CPU bus, there is also a bridge connecting the fast CPU bus to the (slower) system bus (also
called the peripheral bus). Whenever the CPU comes out with a read, say, whose address is within the
range allocated to the peripheral bus (say 0x8000 to 0xafff), then the bridge notices this and create a
corresponding read transaction on the peripheral bus. When that transaction is complete (that is, the
correct peripheral has returned the data), the bridge returns the data to the CPU via the CPU bus.
The system bus of the RSoC is the XBus, our faithful golden eVC bus.
The reason we have chosen this bus for the example is that it (and the XCore that sits on it, see below)
are well known to anyone who has studied eRM.

2.2.5

The Peripheral Controllers

There are several peripheral controller modules (also called devices) on the peripheral bus. Each
peripheral controller communicates with the outside world in its own unique way.
Specifically, there are two XCore serial interfaces, a USB interface, and an Ethernet interface.

2.2.6

Registers and the Magic of Memory-Mapped IO

Each peripheral controller contains several registers, and each such register is mapped to some address
in CPUs address space. This is called memory-mapped IO.
For example, the XCore tx_mode register (which controls the transmission of the next serial frame)
might be mapped to address 0x8000, while the XCore rx_mode register is at address 0x8001.
With two XCore modules in this SoC, the registers of XCore0 may be mapped starting at 0x8000, and
the registers of XCore1 may be mapped starting at 0x8040. In general, the CPU controls the peripherals
by writing to their control registers and then reading from their status/data registers. A peripheral might
have just a few bits of control and status, or it might have hundreds of flags, modes and internal tables.
Thus, the memory map (as it is called) might look something like this:
[0x0..0xff]:
...
[0x8000..0x803f]:
[0x8040..0x807f]:
...
0x10000..0xffffffff]:

Interrupt vectors
XCore1 registers
XCore2 registers
External memory

We will soon see how to handle this using the register package.

2-8

Version 2.0 Beta 1

System Verification Methodology

Introduction to SoC Verification


The DMA

2.2.7

The DMA

A DMA (Direct Memory Access) is a device that can move data from one place to another. Each place
is usually a sequence of memory locations, but it could also be some peripheral device.
The DMA itself is programmed by the CPU. It has registers signifying, for example, the from and to
addresses, the number of elements to move, the size of each element, etc.
Thus, if the CPU wants to read data from the serial line, it has two choices:

Read each byte directly from the rx_data register


Program the DMA (by writing to the DMAs registers) to read a sequence of bytes from the rx_data
register as the bytes become available
Note The DMA and the CPU can act as bus masters (they can request a memory cycle), whereas the
XCore can only act as a slave (it allows someone else to access its memory-mapped locations). The more
masters we have on our SoC, the more complex the picture is.

2.2.8

Variations on a Theme

There are many variations on this picture. For the purposes of this introduction, we can safely ignore
these variations. However, the sVM cookbook will discuss them at length.
Here are some of the variations:

The CPU itself could actually reside outside the chip. This is not all that different from when it resides
inside.

Other than the plain DMA, there could be real data-crunching modules inside the SoC, which, for
example, take data from one memory, compress it, and put it in another memory. For now, you can
think of these as just glorified DMAs.

Many SoCs have a DSP in addition to the CPU. They also can have several more processors.
Most SoCs today have more than two buses. Those buses might not even share the same address
space. (For example, address 0x8000 on one bus might address the XCore, but address 0x8000 on
another bus might address some memory.)

The whole SoC design could be configurable. In other words, you could be called upon to build a
verification environment that works regardless of whether the device has one XCore or two, a 16-bit
bus or a 32-bit bus, etc. The most general case is called a platform, that is, a basic design to which
platform users can add their own extensions.

System Verification Methodology

Version 2.0 Beta 1

2-9

Introduction to SoC Verification


What Does SoC HW Verification Mean?

2.2.9

What Does SoC HW Verification Mean?

Perhaps we should first ask: What is it that should be verified in the SoCs HW?
We could spend a lot of time verifying the various pieces such as the CPU. But it (and most other pieces)
are supposed to come pre-verified, and in fact often come with their own eVCs.
So, what does verification mean in an SoC? The most common answer is:
Verify that the programmers model of the SoC is correct.
The programmers model of the SoC describes how a (SW) programmer should use the SoC. It says
(either explicitly or implicitly) things like:
To activate the DMA, write the appropriate control bits to the 16-bit DMA_CTRL register at
address 0x9000. The START bit (bit 0) should be set to 1. If you want an interrupt when the DMA
is done, write a 1 to the INT_AT_END bit (bit 5).

2.2.10

Typical SoC Bugs

To help us understand what needs to be verified in an SoC, this section discusses some typical SoC bugs:

Bugs in new modules


Wrong assumptions about some module
Badly wired module
Problems arising from interactions:
Can the Ethernet controller write to memory and the DMA read from memory at the same time?
If two modules signal interrupt, can they be differentiated?

2.2.10.1 Bugs in New Modules


Any new module created for this project is, of course, considered more dangerous than trusty old
modules.
In the RSoC, let us assume that the only new modules are the XCore and the Ethernet controller.
Thus, the XCore should be verified separately (see below) in addition to being verified in the context of
the full HW.
Luckily, the XCore can be verified in isolation. Components like the DMA are much harder to verify in
isolation, because their job is to interact with other components.

2-10

Version 2.0 Beta 1

System Verification Methodology

Introduction to SoC Verification


Verifying the SoC HW

2.2.10.2 Wrong Assumptions about Some Module


The specs of the modules might be unclear or underspecified. Some examples are:

Can I write to two subsequent 8-bit registers using one 16-bit write, or must I do two writes?
Is it legal to read the status register of a peripheral before it was initialized?

2.2.10.3 Bad Module


One of those supposedly pre-verified modules might be not-so-verified after all.
If the module(s) come with an eVC, take a good look at that eVC:

Is it eRM compliant?
Can you rerun the tests?
What is covered?

2.2.10.4 Badly Wired Module


This could cause the modules registers to be at the wrong address, etc.

2.2.10.5 Problems Arising from the Interaction of Modules


Each module might work fine in isolation, but timing or other problems arise when they work together.
For example:

In our RSoC, even if the you have previously verified that the Ethernet controller can write to the
internal DRAM and the DMA can read from the DRAM, strange and interesting bugs can appear
when the two activities are happening concurrently.

If two modules are trying to interrupt the CPU at the same cycle, will this work? Will there be a
reliable way for the programmer to determine the two causes of the interrupt?

2.3

Verifying the SoC HW

In this section we will first discuss how to verify the XCore and then how to verify the full hardware.
It is vastly oversimplified, concentrating on driving input.

System Verification Methodology

Version 2.0 Beta 1

2-11

Introduction to SoC Verification


Verifying the XCore

2.3.1
Figure 2-4

Verifying the XCore


XCore eVC Unit Verification

As you can see in Figure 2-4, we have created an XCore eVC that uses the interface eVCs of the two
interfaces of the XCore (namely XBus and XSerial).
We are using the register/address space package to define the register block containing the four XCore
registers. We further use this package to hook this block up to the XBus address space, so we can
generate register values and then drive them through the XBus to the correct registers.
On top of that, we build a specific Program-the-XCore sequence, which (given some parameters)
programs the XCore to do reception or transmission according to the parameters. This
Program-the-XCore sequence writes to the XCore registers, much like a (SW) device driver does.
Finally, there is a multi-channel sequence driver, which will call Program-the-XCore, and at the same
time send serial frames to the XCore through its serial interface.
There are many other important details regarding checking, coverage, and debugging, but we will skip
them for now.

2.3.2

Verifying the Full RSoC Hardware Environment

Figure 2-5 shows the environment for driving inputs into the full RSoC hardware.

2-12

Version 2.0 Beta 1

System Verification Methodology

Introduction to SoC Verification


Verifying the Full RSoC Hardware Environment

Figure 2-5

RSoC Hardware Verification

We assume that all modules come with their interface eVCs, complete with items, sequence drivers,
BFMs, and monitors.
We further assume that each module that has registers and can be programmed (XCore, USB, Ethernet,
DMA) already comes with a highly-parameterized Program-the-module sequence that programs the
corresponding module via the bus.
OK, so we have the raw materials. What do we do next?

2.3.2.1

Yank Out the CPU

First, we remove the CPU and replace it with an AHB eVC.


Yanking out the CPU is an extreme but very justifiable act, because then we can put everything under
sequence control.

2.3.2.2

Create a Family of Bus Sequences Emulating the Software

Much of what happens next depends on having a bus eVC with a sequence driver.
While there is no real software in this picture, we are in fact going to mimic what a normal software
program would do with a bunch of bus sequences.

System Verification Methodology

Version 2.0 Beta 1

2-13

Introduction to SoC Verification


Checking

The Init Sequence


At the top level we need to call an initialization sequence. That initialization sequence configures things
that only need to be configured once (for example, the frequency of the timer).
Note For the last time, let me repeat that nothing I say here is the full truth. Every advice (including
this last one) is sometimes inappropriate. For example, you might want to re-program the timer frequency
on the fly. I am simplifying things. But lets move on.
When the init sequence is done, the main sequence launches in parallel the interrupt and dispatcher
sequences.

The Interrupt Sequence


The interrupt sequence sits there doing nothing, waiting for some device to interrupt the CPU. When that
happens, it acts much like a real interrupt routine:

It reads the interrupt status register.


It reads enough status information from the interrupting device and updates some global status
information regarding that device (for example, whether it is now idle or busy).

The Dispatcher
The dispatcher runs in a loop, doing the following:

Deciding which device to activate next


Waiting until that device is idle (done by either looking at the global status kept by the interrupt
routine or polling the device status register directly)

Programming the device to do some random, good work

2.3.2.3

Controlling the Other Side

While all of this good stuff is happening on the bus side, we must do things on the interface side (serial,
Ethernet, etc.).
Figure 2-5 shows a multi-channel sequence coordinating the two sides, but we could also let the

interface side proceed independently.

2.3.3

Checking

Here is a brief summary of checking considerations.

2-14

Version 2.0 Beta 1

System Verification Methodology

Introduction to SoC Verification


Coverage

Existing module checks should stay.

Turn off only for performance


The system is more than the sum of its parts.

Add end-to-end checks


Add checkers for new semantics
Monitors should broadcast everything they see.

Can use method ports for this


Scoreboard methodology

Global scoreboard? Multiple scoreboards?


Are scoreboards updated when detecting internal op?
Problem: Exact timing may have far-reaching consequences.

Problematic for reference models unless very accurate


Problem: Some systems need human eyes or ears for checking.

2.3.4

Coverage

Here is a brief summary of coverage considerations.

System Verification Methodology

Version 2.0 Beta 1

2-15

Introduction to SoC Verification


Verifying the HW with the SW

Using sub-modules coverage:

Turning some off for scalability


Adding illegal/ignore
Automatically removing generation coverage for internal interfaces
Covering inter-module interactions:

Data flow (for example, from Ethernet input via memory to XCore output)
Throughput/utilization
Coverage of shared resource access
System-level coverage:

New functionality within the system


Coverage of system configuration (including configuration of each unit)
Crossing multiple eVC instances:

Ability to explicitly sample into fields (to be used later)

2.4

Verifying the HW with the SW

We now turn our attention to the tricky job of verifying the chip with the software. There are two layers
to be verified here. Each has different needs:

Verifying the chip with the device drivers is best done against the RTL simulation. It is accurate,
available early, and fast enough.

Verifying the chip with the post-silicon requires much more speed. Therefore, we do it on the real
hardware.
Figure 2-6 describes the various trade-offs regarding simulation modes and their speed. For the RSoC,

we developed no high-level model. We verified everything but the application SW against the RTL.

2-16

Version 2.0 Beta 1

System Verification Methodology

Introduction to SoC Verification


Verifying the HW with the SW Device Drivers

Figure 2-6

2.4.1
Figure 2-7

Simulation Modes

Verifying the HW with the SW Device Drivers


Driver and Hardware Verification

System Verification Methodology

Version 2.0 Beta 1

2-17

Introduction to SoC Verification


Verifying the HW with the SW Device Drivers

In Figure 2-7, the bottom part has not changed. We still send data to the various interfaces. But the top
part is different now. Essentially, we need some dispatcher sequence that will generate randomly (but
with some logic):

The identity of the next device driver routine to call (for example, ened_send_buffer())
The values for the various parameters
But how do we actually call the chosen C/C++ routine? In the rest of this chapter, I will discuss a few
possibilities.

2.4.1.1

Via Method Ports

This is the best approach. It is just now becoming available. It is also the approach depicted in Figure
2-7.
Essentially, after somebody has written the correct ESI adaptor, you just:
1.

Define a method port for each routine you want to call.

2.

Bind it to the correct C routine in the driver (for example, enet_send_buffer()).

Then, at runtime, the sequence just needs to call the method port with the chosen parameters.
Note Method ports may eventually encapsulate some of the other options (for example, CVL).

2.4.1.2

Create and Load Code

This means that we go completely for pre-generation.


1.

Pre-create all of the transactions (as a list).

2.

Translate each transaction, for example, to C source.

3.

Compile and link the created source file.

4.

Load the resulting binary code into memory, ready for the CPU to execute it.

This works, but pre-generation is a pain. You can no longer control the timing according to the DUTs
behavior. Therefore, there are other options.
On the other hand, a conservative (in other words, realistic) verification engineer will insist on running
at least some of the tests this way. That is because the other options employ various degrees of trickery,
and we must also test the real thing.

2-18

Version 2.0 Beta 1

System Verification Methodology

Introduction to SoC Verification


Verifying the Hardware with the Application Software

2.4.1.3

Create an Interpreter for Read/Write Requests

This is like the above, but the C main program acts as a slave, performing calls to routines according to
orders coming from the Specman sequence via some mailbox in memory.
You can encapsulate all of that via method ports, in which case the C main program and the mailbox are
created automatically.

2.4.1.4

Seamless and Such

Mentors Seamless is the leading HW/SW co-verification tool (and about the only one left). It has
facilities to load the SW, run and debug it, while communicating with the HDL simulator and keeping
the two synchronized. You can also tell it, say, that only memory accesses to memory-mapped devices
will activate the simulator (and thus access to program memory will happen in zero simulation time).
It has a library of tens of specific CPUs and DSPs. For each, you get an instruction set simulator, a BFM
corresponding to that CPUs bus interface, and a debug environment.
Seamless is integrated with Specman in the sense that they can attach to the same HDL simulator and in
the stronger sense that Specman can access the SW state much like it can access the HW state. This is
good for coverage and checking.
Here too you can go for any of the three options:

Pre-generation
Communication with the Specman sequence driver via a mailbox
Encapsulating the mailbox in a method port

2.4.1.5

CVL

CVL (Co-Verification-Link) is the Specman built-in tool for HW/SW co-verification. It is not as
powerful as Seamless, but it comes free with Specman and is probably easier to operate.
It is basically a remote procedure call interface between an external C program and Specman. The C
program can call the AHB sequence driver directly and send it an AHB burst.
Here too you can go for the same three options.

2.4.2

Verifying the Hardware with the Application Software

Finally, we are left with verifying the full HW with the application software.
This is even trickier to do, because it needs both speed and control. Figure 2-8 shows one way to do it.

System Verification Methodology

Version 2.0 Beta 1

2-19

Introduction to SoC Verification


Verifying the Hardware with the Application Software

Figure 2-8

Full Hardware

What happens here is:


1.

The actual RSoC (either in ASIC form or some FPGA prototype) sits on a prototype board.

2.

Specman generates interesting multi-channel transactions to the serial, USB, and Ethernet interfaces
(but not to the bus/software the software is now free-running).

3.

The transactions are fed into the actual interfaces in the prototype board via some hardware interface
or test equipment.

This last, innocent step is the most problematic, of course. It can be done in one of the following ways:

Via eCelerator
By having Specman program, say, some Ethernet/USB test equipment
By having Specman (running, say, on a Linux machine) program directly some interface cards for
the needed protocol, which are connected to the board
Notes

Sometimes, for speed reasons, Specman must pre-create all of the inputs and then start feeding stuff
via the hardware interface.

The verification environment modeled in Specman must be at the corresponding (high) level of
abstraction. For example, remember that a typical scenario at this level is:
<scan-carrots> <scan-milk> <total> <swipe-credit-card>
<receive-bad-credit-response> <receive-corrupted-packet> <total>

<scan-carrots> probably corresponds to a specific, multi-packet USB sequence that must be


modeled.

2-20

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System


Level

This chapter uses a small example to show the relationship between module and system eVCs and to
explain the methodology of constructing a system verification environment while reusing module-level
components.
The example DUT, QSoC, contains two instances of the XCore on a single XBus. Each XCore is
connected to an XSerial port. The system is activated by software running on an XBus master.
To demonstrate the module-to-system methodology, we use the XCore as the module level example with
a corresponding module eVC. The QSoC is a hardware subsystem that has a corresponding QSoC eVC.
The QSoC_D, containing the software with the hardware, is the example for the system.
Figure 3-1

The Golden Example QSoC_D DUT

QSoC_D DUT
SW_driver

QSoC
XCore0

System Verification Methodology

XCore1

Version 2.0 Beta 1

3-1

From Module Level to System Level

A system in one verification environment can become a subsystem in a larger environment. The terms
module eVC and system eVC are interchangeable. A module eVC is a system eVC for a single module.
This small example is actually part of a more complete system named the RSoC, which serves as the
demo testbench for sVM.
Figure 3-2

The RSoC DUT

RSoC DUT
CPU

DMA

Memory
AHB

Bridge
XBus
XCore

XCore

USB

Ethernet

This chapter contains:

System eVCs on page 3-3


Module and System eVC Architecture on page 3-6
Integrating eVCs into an SVE on page 3-15
Configuration on page 3-17
Sequences on page 3-21
Coverage on page 3-23
Checking on page 3-26
See Also
XCore eVC User Guide (svm_lib/vr_xcore/docs/vr_xcore_evc.pdf)
QSoC eVC User Guide (svm_lib/vr_qsoc/docs/vr_qsoc_evc.pdf)

3-2

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System Level


System eVCs

3.1

System eVCs

A system eVC is a reusable verification environment for a system. It contains module/subsystem eVCs,
interface eVCs, and some additional verification components for the system level.
An interface eVC (for example, AHB, PCI, or Ethernet) is a generic eVC for verifying the protocol on
the interface.
System eVCs

Drive system-level scenarios


Monitor the behavior of the system
Collect system-level coverage

Interface eVCs

Define the interface data item (packet, burst)


Drive the items using sequences with the predefined sequence driver and
BFM

Monitor the items (collecting the items and interpreting the related events)
for checking and coverage

Check the protocol


This section contains:

Verifying Systems on page 3-3


Structure and Functionality of System eVCs on page 3-4
System eVC Packages on page 3-5

3.1.1

Verifying Systems

The first step in system verification is integrating all of the components into a system verification
environment. This means instantiating the module, subsystem, and interface eVCs and connecting them.
Each component must be configured to create a consistent model of the actual system DUT.
In the RSoC example, the components are:

Interface eVCs (XBus, AHB, XSerial)


Module and subsystem eVCs (QSoC, XCore, XBridge, QSoC_SW)
The next step is adding the system-specific capabilities such as system-level driving (virtual sequence
driver), system-level logic checking (scoreboards), and system-level coverage.
In the RSoC example, the system-specific capabilities are:

Driving multiple interfaces concurrently


System Verification Methodology

Version 2.0 Beta 1

3-3

From Module Level to System Level


Structure and Functionality of System eVCs

Collecting and covering flow-control data (not implemented)


Checking transformation from AHB transfers to XBus transfers (not implemented)
Verifying a system requires expertise in respect to:

Multiple interface eVCs


Development of system-specific components
System eVCs encapsulate all of the above and let you reuse the same in multiple verification projects.

3.1.2

Structure and Functionality of System eVCs

The role of the system eVC is to encapsulate all knowledge about its components and add the specific
verification components needed to verify the system. The main objective is wide-ranging reuse:

From module to system to larger systems


Between projects
TLM to cycle-accurate to post-silicon
The main candidates for reuse are:

Data items (for example, packets and registers)


Sequences (sequence libraries)
Coverage definitions
Checks and scoreboards
Reference models
vPlan
The following partially reusable components can be copied to a new environment and modified slightly:

Topology
Configuration of sub-eVCs
Building a system eVC makes use of the following elements provided in the components:

3-4

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System Level


System eVC Packages

Interface eVCs

Traffic generation
Data items
BFM and sequence driver
Basic sequences
Checks
Protocol checks
Scoreboard
Coverage definitions

Module and Subsystem eVCs

Relations between participating eVCs


Connections between scoreboards and appropriate monitors
Module-specific checks
Internal checks
Reference model
Module coverage
Fine-tuning of interface eVCs coverage definitions
Cross coverage
Internal coverage

3.1.3

System eVC Packages

The system eVC is developed and maintained as an eRM package with some additional subdirectories.
The objective is to encapsulate in a reusable package all necessary code, examples, and documentation
for verification of the system.
In particular, the eVC contains examples of how to reuse this system as a component in a larger system.
These examples are contained in one or more SVE (Simulation and Verification Environment)
directories, the content of which is described in Module and System eVC Architecture on page 3-6. An
SVE example should be used as the basis for integration of the system eVC in a larger system.

System Verification Methodology

Version 2.0 Beta 1

3-5

From Module Level to System Level


Module and System eVC Architecture

3.2

Module and System eVC Architecture

Figure 3-3

The XCore DUT


XBus eVC
XBus

XCore Module eVC

XCore

XSerial
XSerial eVC

The architecture of module/system eVCs is different from interface eVCs. The example used here is that
of the XCore DUT, which has a bus interface connected to the XBus and a serial interface connected to
an XSerial port. The XCore transfers streams of bytes in either direction.
When designing the verification environment for this example, the first considerations that must be
addressed are:

What eVCs will be involved?


What will the module eVC contain?
What will be the eVC interactions?
This section contains:

Module eVC Architecture on page 3-7


System eVC Architecture on page 3-8
System eVC Monitor on page 3-8
Stand-In Mode on page 3-12
Reference Model on page 3-14

3-6

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System Level


Module eVC Architecture

3.2.1
Figure 3-4

Module eVC Architecture


The XCore eVC

XCore Module eVC


Addr Map

Reg File

VSD
seq

RSD
seq

Monitor
Scoreboard

ACTIVE
Stand-In Model
VSD

Ref Model

seq

In general, a module eVC includes:

A monitor for collecting and interpreting events and data going to/from the DUT
Events, checks, and coverage
(Optional) A scoreboard and a reference model
Memory blocks and register files
A Virtual Sequence Driver (VSD) and a Register Sequence Driver (RSD) instantiated in the SVE or
a higher-level system eVC that uses the module eVC as a component

The VSD is defined in the eVC but is used on a higher level


The RSD is defined in the register and memory package
The eVC has active and passive subtypes. The active subtype implements the stand-in mode, where the
module eVC plays the role of the DUT (for example, when the DUT is not available). The active
subtype contains an additional sequence driver used to drive the simulation instead of the DUT.
The module eVC is connected (using pointers or ports) to other eVCs, in particular to the related
interface eVCs monitors and BFMs.

System Verification Methodology

Version 2.0 Beta 1

3-7

From Module Level to System Level


System eVC Architecture

3.2.2
Figure 3-5

System eVC Architecture


The QSoC eVC

QSoC System eVC


Addr Map

XCore Module eVC

VSD

XCore Module eVC

Reg File

Reg File

seq

Monitor

RSD

Scoreboard

ACTIVE
Stand-In Model

Monitor

ACTIVE
Stand-In Model

Scoreboard

VSD

seq

Ref Model

seq

VSD

Ref Model

seq

VSD
seq

System eVCs are similar to module eVCs. In general a system eVC includes:

Module eVCs representing the modules that comprise the system


An address map representing the address space of the memory blocks and register files in the various
subcomponents

A Virtual Sequence Driver (VSD) and a Register Sequence Driver (RSD) instantiated in the SVE or
a higher-level system eVC that uses the system eVC as a component

The VSD is defined in the eVC but is used on a higher level


The RSD is defined in the register and memory package
The system eVC is connected (using pointers or ports) to other eVCs, in particular to the related
interface eVCs monitors and BFMs.

3.2.3

System eVC Monitor

The monitor in a system or module eVC is a critical component in the verification environment. It
obtains and maintains events and data related to the activity in the module or system. This information
is made available to checkers, scoreboards, and coverage collectors.

3-8

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System Level


System eVC Monitor

The monitor collects most of the information from the relevant interface eVCs. Some additional
information relating to the internal state of the module or system might be derived either from the DUT
(whitebox access) or from the reference model.
The connection of the monitor to the corresponding interface eVC monitors is done using either pointers
or ports. Using pointers limits the ability to eCelerate the monitor. If the required information is
available from the interface eVC through ports, use them instead.
This section contains:

Connecting the Monitor with Pointers on page 3-9


Connecting the Monitor with Ports on page 3-10
System eVC Monitor Example on page 3-11

3.2.3.1

Connecting the Monitor with Pointers

When using pointers, the following connections are needed for the module/system eVC to the interface
eVC:

System eVC env ==> Interface eVC envs


System eVC env ==> Interface eVC agents
System eVC monitor ==> Interface eVC monitors
System eVC Sequence Driver ==> Interface eVC Sequence Driver
Avoid using pointers in the opposite direction (in other words, no interface eVC to system eVC
pointers). The interface eVC is a generic tool. It should be independent of the actual module eVCs using
it.

System Verification Methodology

Version 2.0 Beta 1

3-9

From Module Level to System Level


System eVC Monitor

Figure 3-6

Connecting the Monitor with Pointers

XBus eVC

ACTIVE
Master

PASSIVE
Slave

SD
seq

Mon

BFM

...

Mon

XCore Module eVC


Reg File
ACTIVE

Monitor

Stand-In Model

Scoreboard

VSD

Ref Model

XSerial eVC

seq

Agent
SD

seq

Mon

3.2.3.2

Mon

BFM

Connecting the Monitor with Ports

When using ports to connect the system/module eVC to the interface eVCs, the interface eVC monitors
must export through ports:

Event ports for protocol events (for example, start and end transaction events)
Simple ports for current data items (for example, packet, burst, etc.)
Method ports to pass data to the scoreboards

3-10

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System Level


System eVC Monitor

Figure 3-7

Connecting the Monitor with Ports

XBus eVC

ACTIVE
Master

PASSIVE
Slave

SD
seq

Mon

BFM

...

Mon

XCore Module eVC


Reg File
ACTIVE

Monitor

Stand-In Model

Scoreboard

VSD

Ref Model

XSerial eVC

seq

Agent
SD
seq

Mon

3.2.3.3

Mon

BFM

System eVC Monitor Example

This code example taken from the XCore eVC shows how the module eVC monitor uses information
collected from other monitors. The example assumes pointer connection between the eVCs.
unit vr_xcore_monitor_u {
-- Pointers to the interface eVC monitors
!xbus_agent_monitor : vr_xbus_agent_monitor_u;
!xserial_rx_monitor : vr_xserial_monitor_u;
!xserial_tx_monitor : vr_xserial_monitor_u;
-- Info from the XBus monitor:
!cur_xbus_transfer : MONITOR vr_xbus_trans_s;
-- An in method port for getting XBus transfers
System Verification Methodology

Version 2.0 Beta 1

3-11

From Module Level to System Level


Stand-In Mode

xbus_transfer_ended : in method_port of vr_xbus_transfer_complete


is instance;
xbus_transfer_ended(transfer : MONITOR vr_xbus_trans_s ) is {
cur_xbus_transfer = transfer;
};
};

3.2.4

Stand-In Mode

Module eVCs should be designed to support stand-in (active) mode. In stand-in mode the system eVC
drives the simulation by playing the role of the DUT. A reference model is used to emulate the device
behavior.

3-12

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System Level


Stand-In Mode

Figure 3-8

Module eVC in Passive (Normal) Mode

XBridge SVE

AHB eVC
ACTIVE
Master

Addr Map

PASSIVE
Slave

Bus
Monitor

SD
seq

RSD

Mon

BFM

Mon

seq

XBridge Module eVC

DUT

Reg File

VSD
seq

AHB
ACTIVE

Monitor

XBridge

Scoreboard

XBus

Ref Model

Addr Map

RSD

XBus eVC
ACTIVE
Master

seq

PASSIVE
Master

Passive
Slave

Bus
Monitor

SD
seq

Mon

BFM

Mon

Mon

When the module eVC becomes active, its corresponding agents in the interface eVCs become active as
well. The sequence driver in the active part of the module eVC is layered on top of the sequence drivers
in the interface eVCs. The built-in driving capabilities of the interface eVCs are used by the module eVC
to drive the simulation.

System Verification Methodology

Version 2.0 Beta 1

3-13

From Module Level to System Level


Reference Model

Figure 3-9

Module eVC in Stand-In Mode

XBridge SVE

AHB eVC
ACTIVE
Master

Addr Map

RSD

Mon

seq

ACTIVE
Slave

SD

SD

seq

seq

BFM

Mon

Bus
Monitor

BFM

XBridge Module eVC

DUT

Reg File

VSD

AHB

Monitor

seq

ACTIVE

Scoreboard

XBridge

Stand-In Model

XBus

VSD

Ref Model

Addr Map

XBus eVC
ACTIVE
Master

RSD
seq

Mon

3.2.5

seq

ACTIVE
Master

SD

SD

seq

seq

BFM

Mon

BFM

Passive
Slave

Bus
Monitor

Mon

Reference Model

Reference models can be implemented at three levels of precision:


Rough Justification

Given some input and some output, check the validity of


DUT behavior

Might use DUTs internals for justification

3-14

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System Level


Integrating eVCs into an SVE

Transaction-Level Functionality

Given an input, provide a list of valid outputs


Used for scoreboards (comparing actual to predicted)
Used for functional stand-in mode

Cycle-Accurate

Given an input, perform cycle-accurate emulation and


provide the expected result

Used for cycle-accurate stand-in mode


An overkill for scoreboards

3.3

Integrating eVCs into an SVE

When building a system-level eVC, the first question is where to instantiate each lower level eVC. If a
module eVC such as the XCore needs services from an interface eVC such as the XBus, it might make
sense to instantiate the interface eVC in the module eVC. However, in that case, multiple instances of
the module eVC would end up with multiple copies of the same interface eVC, which is undesirable.
So the rule is to instantiate each eVC on the level that encapsulates all of the eVCs that depend on it.

The system eVC instantiates the eVCs (module, subsystem, or interface) that are fully encapsulated
in the system. (For example, the QSoC eVC has two instances of XCore.)

The SVE instantiates the eVCs that are not fully encapsulated in the eVCs. (In the QSoC example,
the XSerial and XBus eVCs are instantiated in the SVE.)
All eVCs and the connections between them are created during generation. This section deals with the
best known practice of generating and connecting eVCs, considering current limitations and future
improvements:

Decide when to use pointers and when to use ports


Resolve generation issues such as:
Generation order
Connecting cross pointers between brothers
This section contains:

Connecting eVCs with Pointers on page 3-16


Recent Improvements on page 3-17

System Verification Methodology

Version 2.0 Beta 1

3-15

From Module Level to System Level


Connecting eVCs with Pointers

3.3.1

Connecting eVCs with Pointers

This section describes the best known practice with current technology. This is a temporary solution. It
will change once additional capabilities are available.
To connect eVCs with pointers:
1.

In the system eVC, define the pointers from the system eVC to the interface eVCs.

2.

In the SVE, instantiate the eVCs.

3.

In both the eVCs and the SVE, connect the pointers procedurally.

Step 1: Define the pointers from the system eVC to the interface eVCs
unit vr_qsoc_env_u like any_env {
-- A pointer to the XBus eVC
!xbus_evc : vr_xbus_env_u;
-- Point to the two XSerial interfaces
!xserial_0_evc : vr_xserial_env_u;
!xserial_1_evc : vr_xserial_env_u;
};

Each system eVC connection (for example, the QSoC connections to the XBus) has a corresponding
interface eVC agent. You might need additional pointers to the agents and their components (for
example, the monitor).
Avoid pointers in the opposite direction. The interface eVC should be independent of the system eVCs
associated with it.
Note These pointers can be used only during run time, not during generation itself.

Step 2: Instantiate the eVCs in the verification environment


unit vr_qsoc_sve_u {
-- One instance of QSoC eVC
qsoc_evc : vr_qsoc_env_u is instance;
-- One instance of the XBus eVC
xbus_evc: VR_QSOC_XBUS vr_xbus_env_u is instance;
-- Two instances of the XSerial eVC
xserial_0_evc: VR_QSOC_XSERIAL_0 vr_xserial_env_u is instance;
xserial_1_evc: VR_QSOC_XSERIAL_1 vr_xserial_env_u is instance;
};

3-16

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System Level


Recent Improvements

Step 3: Connect the pointers procedurally


The pointers between eVCs are connected procedurally after generation of the architecture. The
connect_pointers() method is activated in a top-down fashion. The method is called automatically after
all units have been generated and the pointers of the parent unit have been connected by the parent units
connect_pointers() method.
extend vr_qsoc_sve_u {
connect_pointers() is also {
qsoc_evc.xbus_evc = xbus_evc;
qsoc_evc.xserial_0_evc = xserial_0_evc;
qsoc_evc.xserial_1_evc = xserial_1_evc;
};
};

Note The connect_pointers() method is a new member of any_unit. It is activated automatically at


the end of the generation phase to perform procedural assignment of pointers. This feature is available in
Specman Elite versions 5.0 and higher. If you work in Specman Elite 4.x, you must include the file
svm_util/e/patch_ec_encapsulation.e.

3.3.2

Recent Improvements

In Specman Elite 5.x, three new phases are added after the unit tree is fully generated. These subphases
allow procedural connection of pointers and ports.
The subphases are implemented as hook methods of any_unit. They are activated in a depth-first order
from sys.

connect_pointers() is a subphase for setting cross pointers procedurally.


connect_ports() is a subphase for binding ports procedurally using the do_bind() method and doing
final settings that depend on pointers set in the previous phase.

check_generation() is a subphase for user-defined sanity checks, including the connection checks
done in the previous phases.

3.4

Configuration

The eVC configuration is a reusable aspect that must be encapsulated with the eVC. When an eVC
becomes part of a system, some of its configuration is fixed according to the specific use in the system.
For example, when the system integrator assigns an XCore to be slave S0 on the XBus, that part of the
configuration should be packaged into the system eVC.
The interface eVC developer creates a general purpose verification environment for a given protocol.
The configuration of the eVC is left to the integrator.

System Verification Methodology

Version 2.0 Beta 1

3-17

From Module Level to System Level


Configuration

The module eVC developer creates a special purpose verification environment for a specific module.
The module eVC uses interface eVCs and imposes certain constraints on their configuration.
The system eVC developer creates a verification environment for a system. The system eVC uses
module and interface eVCs and imposes further constraints on the configuration.
Finally, the system integrator creates the simulation and verification environment for a project. The SVE
uses system, module, and interface eVCs and sets the final configuration.
Who knows what?

The interface eVC developer knows how to configure the interface eVC.
The module eVC developer knows how to configure the module eVC and might know something
about configuring the interface eVC.

The module eVC user (developing a module DUT or developing a system eVC) knows something
about the module, but probably knows very little about the interfaces and the interface eVCs.
The challenge for the system eVC user is to configure correctly all of the sub-eVCs.
The challenge for the eVC developer is to pre-configure the eVC to ease the process of integration while
maintaining the necessary flexibility.
eVC Configuration includes:

The configuration struct


Fields affecting the verification process (knobs)
Configuration constraints
Assigning signal names
Specifying address spaces
Specifying subtypes
Agent type, operation mode
Controlling the operation mode using type definitions
Bus width
This section contains:

Configuration Struct on page 3-19


Configuration with Constraints on page 3-19
Extending Subtypes on page 3-19
3-18

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System Level


Configuration Struct

Defining Types on page 3-20


SVE Configuration File on page 3-20

3.4.1

Configuration Struct

Each level in the unit hierarchy can have a configuration struct. Configuration is always projected top
down, typically using constraints from the parent.

The configuration of a component depends only on the configuration of the parent environment.
If the configuration of siblings is mutually dependent, the dependency must be generated in the parent
environment and propagated down to the siblings.

3.4.2

Configuration with Constraints

Each eVC defines a default configuration for each sub-eVC, either using soft constraints or by providing
the constraints in a file that can be imported either by the SVE or by a higher-level eVC but not by the
eVC top file.
In the SVE config file, you can override the soft constraints when necessary or decide which of the
configuration files to import.
extend vr_qsoc_env_u {
keep soft xcore_evc0.sig_reset == "xbus_reset";
keep soft xcore_evc0.monitor.sig_base_addr == "base_addr";
keep soft xcore_evc0.hdl_path() == "xcore_a_inst";
keep soft xcore_evc1.sig_reset == "xbus_reset";
keep soft xcore_evc1.monitor.sig_base_addr == "base_addr";
keep soft xcore_evc1.hdl_path() == "xcore_b_inst";
}; // extend vr_qsoc_env_u

3.4.3

Extending Subtypes

Each agent and env unit has a name field that can be assigned in the eVC. Unique names are used to
constrain the individual units as follows:
extend VR_XCORE vr_xserial_env_u {
keep agent.direction == TX_AND_RX;
};

This unique naming serves one aspect only. Occasionally you might find other uses for this naming. For
example, the XCore is used to build the QSoC eVC. In that case:

System Verification Methodology

Version 2.0 Beta 1

3-19

From Module Level to System Level


Defining Types

You might want to use the name to identify the XSerial port of XCore.
You might also want to identify the XSerial port of QSoC.
Each unit has only one name field. Therefore, you must choose a consistent naming convention. Naming
should be deferred to the instantiation. In the following example, the two XSerial eVCs are named in the
SVE where they are instantiated, rather than in the QSoC eVC.
unit vr_qsoc_sve_u {
qsoc_evc: VR_QSOC_SVE vr_qsoc_env_u is instance;
xbus_evc: VR_QSOC_XBUS vr_xbus_env_u is instance;
xserial_0_evc: VR_QSOC_XSERIAL_0 vr_xserial_env_u is instance;
xserial_1_evc: VR_QSOC_XSERIAL_1 vr_xserial_env_u is instance;
};

3.4.4

Defining Types

It is best to define some operation modes using types, for example the bus width vr_ahb_data_width.
While the type is defined in the eVC, occasionally it must be overridden in the SVE.
The actual bus width is determined only when the bus is instantiated. To allow overriding from the SVE,
the definition of the bus width in the eVC is done using define under #ifndef. For example:
#ifndef VR_AHB_DATA_WIDTH {
define VR_AHB_DATA_WIDTH 32;
};

It can be overridden in the SVE configuration (before importing the eVC) as follows:
define VR_AHB_DATA_WIDTH 64;

3.4.5

SVE Configuration File

The SVE has a configuration similar to the configuration of the eVCs. Its role is to instantiate all
top-level units and to configure them.
Defining the top-level verification components includes:

Instantiating all interface and system eVCs


Adding virtual sequence drivers
Defining the address map and register sequence driver
Adding end-to-end scoreboards
Configuring the verification environment includes:

3-20

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System Level


Sequences

Setting modes of operation


Coordinating test phases (end of test)
Propagating configuration to subcomponents

3.5

Sequences

Driving the verification environment is done using sequences. Reusing sequences from the various
components of the environment saves effort when building the verification environment.
This section contains:

Reusing Sequence Drivers on page 3-21


Reusing Sequences on page 3-21
Sequences: Module to System on page 3-22
Reuse of Register Sequences on page 3-22
Organizing and Using Sequence Libraries on page 3-23

3.5.1

Reusing Sequence Drivers

A virtual sequence driver is always instantiated on the SVE level. Its primary role is to drive coordinated
scenarios involving multiple inputs to the system. These scenarios are built from reusable sequences
from the lower-level eVCs.
Virtual sequence drivers from the module level can be reused (instantiated) on the system level. These
sequence drivers are:

Defined in module eVCs


Instantiated in the SVE of the module eVC (as a usage example)
Reused by instantiating in a system SVE

3.5.2

Reusing Sequences

Module-level sequences are not always reusable on the system level. In general, mixing random
sequences can break a design. For example, inputs that are accessible at module level might not be
accessible at system level.

System Verification Methodology

Version 2.0 Beta 1

3-21

From Module Level to System Level


Sequences: Module to System

3.5.3

Sequences: Module to System

To facilitate module-to-system reuse, each eVC must provide some basic sequences that are reusable on
a higher level.

Each interface eVC must define the basic READ/WRITE access to the DUT.
The module eVC must provide a sequence library with:
Basic READ/WRITE for each of the interfaces, using the interface eVCs and register sequences.
Basic module control sequences.
Basic virtual sequences (activating multiple interfaces), using its own basic READ/WRITE
sequences and the control sequences.

The system eVC must provide a sequence library with:


Basic READ/WRITE sequences, using the module eVC sequences.
Basic virtual sequences (activating multiple modules), using its own basic READ/WRITE
sequences.
Parameters should be used whenever appropriate. Parameterized sequences are more reusable.

3.5.4

Reuse of Register Sequences

Parameters should be used whenever appropriate. Parameterized sequences are more reusable.
The register sequences in the module eVC access the registers in the XCore.

To reuse in a multi-XCore environment, you can constrain the static_item field of vr_ad_sequence.
The XCore sequence library constrains static_item to the register file of the XCore.
The QSoC sequence library constrains static_item to be one of the two register files.
To make the sequence reusable, have xcore as a parameter.
extend VR_QSOC_WRITE vr_ad_sequence {
xcore
: vr_qsoc_xcore_name;
!regs_sequence : vr_ad_sequence;
body() @driver.clock is only {
do VR_XCORE_XBUS_WRITE regs_sequence keeping {
.static_item == driver.addr_map.
reg_file_list[xcore.as_a(uint)];
};
};
};
3-22

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System Level


Organizing and Using Sequence Libraries

3.5.5

Organizing and Using Sequence Libraries

In general, sequences should be maintained in separate libraries. Each library is a file containing several
sequences sharing some common feature. Each library is separately loadable so that only the appropriate
sequences are loaded during simulation. Examples of sequence libraries are:

Basic sequences (reusable)


Module-level sequences only (not likely to be reusable)
Configuration sequences (reusable at every level)
Register sequences for setup and configuration (reusable at every level)
Sequence libraries can reside either in the eVC or in the sve/scenarios directory in the SVE.
Sequence library files are imported by setup files. The role of setup files is to:

Specify which sequences are valid


Define other environment parameters
Setup files are imported by the test files.

3.6

Coverage

Coverage definitions can be reused from module to system, while adding system-specific coverage
definitions.
Interface eVCs collect coverage of traffic on the specific protocol they monitor. Module eVC coverage
is collected in its monitor, based on information from interface eVCs and from the DUT/reference
model.
System-level coverage is based on information in all module and interface eVCs in the system.
Coverage results can be crossed to show interactions and combined states.
This section contains:

Module eVC Coverage on page 3-24


System-Level Coverage on page 3-24
Reusing Coverage on page 3-24
Adding Coverage Definitions to System eVCs on page 3-25

System Verification Methodology

Version 2.0 Beta 1

3-23

From Module Level to System Level


Module eVC Coverage

3.6.1

Module eVC Coverage

The module and system eVCs provide coverage data in different categories such as:

Basic traffic coverage for each of the interfaces


Crossing traffic coverage for all interfaces
Internal coverage (for example, internal states)
Sequence coverage
Register coverage
Performance-related coverage, such as delays and throughput
Configuration coverage, such as all operation modes
Reset and recovery
Hot configuration (where applicable)
Error conditions and recovery

3.6.2

System-Level Coverage

System coverage is very similar to module-level coverage with some exceptions:

Connectivity coverage is very important.


Crossing of all valid configurations of the modules in the system is possible.
There is no internal state on system level.
Lower-level coverage definitions should be reused where applicable (fine-tuned if necessary). Irrelevant
coverage goals should be filtered out on the system level.

3.6.3

Reusing Coverage

To facilitate reuse of existing coverage groups defined in the interface eVC, some modifications might
be needed. You should:

Define meaningful ranges for the system (might be different from the original ranges).
Ignore irrelevant groups or items.
Control coverage collection using the has_coverage flag, assuming it was implemented in the
sub-eVC.

3-24

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System Level


Adding Coverage Definitions to System eVCs

When the XCore is reused on the system level, its coverage definition (as well as the coverage of its
registers) must be modified as follows:
extend vr_ad_reg {
cover reg_access (kind == VR_XCORE_RX_MODE) is also {
item direction using also ignore = (direction == WRITE);
};
};
extend vr_xcore_monitor_u {
post_generate() is also {
covers.set_cover(
vr_xbus_agent_monitor_u.agent_trans_end(name == NO_AGENT),
FALSE);
};
};

By default there is no coverage collection on active slaves. However, if a module eVC operating in
stand-in mode needs the coverage information from the corresponding agent in the interface eVC, it can
turn coverage collection on. For example:
extend S3 vr_ahb_slave {
keep has_coverage == TRUE;
};

3.6.4

Adding Coverage Definitions to System eVCs

To define new coverage groups under the module/system monitor:

Use events from the interface eVC or lower-level monitors.


Use data items from the interface eVC or lower-level monitors
Duplicate coverage definitions from the interface eVC or lower-level eVCs (where needed).
For example, definition of coverage in the XCore is done as follows:
extend vr_xcore_monitor_u {
event tx_frame_started is cycle @xserial_rx_monitor.frame_started;
on tx_frame_started {
cur_tx_frame = xserial_rx_monitor.monitor_frame;
};
cover tx_frame_started is {
item inter_frame_delay : uint =
cur_tx_frame.inter_frame_delay using ranges = {
range([1]);
range([2..100]);
range([101..MAX_UINT]);
};
System Verification Methodology

Version 2.0 Beta 1

3-25

From Module Level to System Level


Checking

item items_in_fifo : uint (bits : 2) = (sig_item_count);


cross inter_frame_delay, items_in_fifo;
};
};

3.7

Checking

In the context of sVM, checking includes both protocol and data checking.
Protocol checks are typically handled by interface eVCs.
Data checks are typically done using scoreboards. If the interface eVC provides a scoreboard, it can be
reused on the system level, assuming that the data item transformation in the DUT is minimal (for
example, a bridge). If the transformation is substantial, a new scoreboard might be required. Instantiate
it either in the eVC or the SVE under a flag.
This section contains:

Connecting the Scoreboard on page 3-26

3.7.1

Connecting the Scoreboard

Connect to the scoreboard via its method ports. The basic scoreboard supports two methods:

add() Add to the scoreboard (only if the data item is expected to be processed by the DUT).
match() Perform the required transformation. Then call the scoreboard with the transformed item.
The basic scoreboard is only responsible for logging and matching the items. Any processing related to
the DUT behavior must be done by the eVC before sending the item to the scoreboard. To assist in this
task, the eVC can use a reference model that predicts the result of the operation.
For example, you could hook the XCore scoreboard to the XSerial agent is done as follows:
unit vr_xcore_monitor_u {
add_to_scbd : out method_port of vr_xserial_add is instance;
find_match_in_scbd : out method_port of vr_xserial_match is instance;
};
extend has_checks vr_xcore_monitor_u {
-- When writing TX frame that the XCore is expected to transmit -- put it on the xbus_to_xserial_scoreboard.
on tx_frame_written {
add_to_scbd$(tx_frame);
message(MEDIUM, "XBus wrote TX frame to XCore: ", tx_frame);
}; -- on tx_frame_written

3-26

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System Level


Scalability Issues in System Verification

-- When reading a frame from the XCore - find its match in the
-- xserial_to_xbus_scoreboard
on rx_frame_read {
find_match_in_scbd$(rx_frame);
message(MEDIUM, "XBus read RX frame from XCore: ", rx_frame);
}; -- on rx_frame_read
}; -- extend vr_xcore_monitor_u

Note Specman Elite 5.x supports multiple binding of method ports. Multiple system-level scoreboards
can be connected using in-method ports, without modifying the module or subsystem eVCs.

3.8

Scalability Issues in System Verification

A system verification environment is assembled from numerous lower level verification environments.
In large systems the performance of the verification environment might become an issue. The first thing
to do in case of performance problems is to compile the verification environment and use the profiler to
look for portions of the code that use too much CPU time or memory space.
If, after compilation and profiling, performance is still unsatisfactory, there are some general guidelines
to improve the performance. These guidelines suggest trading off some features provided by the various
components of the verification environment for better performance. Every eVC contains features needed
for thorough verification of modules. However, there is a performance cost associated with each such
feature.
This section describes the main features to examine for improving performance. It also describes
solutions that some eVCs provide to achieve better performance by giving up some of the power and
flexibility of the eVC.
This section contains:

Stimulus Generation on page 3-28


Checking on page 3-32
Coverage on page 3-33
Messages on page 3-34
eVC-specific Solutions on page 3-34

System Verification Methodology

Version 2.0 Beta 1

3-27

From Module Level to System Level


Stimulus Generation

3.8.1

Stimulus Generation

Sequences are a key component of the eVC, but loading large numbers of sequences can have a
considerable performance penalty when large verification environments are created using many eVCs.
The most effective guidelines in this area are:

Use sequence libraries, and load only what is needed for the simulation.
Use generation judiciously.

3.8.1.1

Sequence Libraries

Sequences should be implemented in sequence libraries. Each library is a separate file containing one or
more sequences and optionally some related code. Sequence libraries should be small and modular, one
or a few sequences in each library. This enables careful selection of just the right sequences for each
simulation.
Some basic sequences are provided as part of the eVC. Additional libraries might be offered as
examples. Finally, most sequence libraries are developed and maintained by the end user during the
verification process.
Sequence libraries may reside in various places.

Basic Library
One or more basic sequence libraries are provided with each eVC. A basic library contains the most
common sequences used in almost every test, such as:

Basic read and write operations for master agents


Basic reactive sequences for slave agents
Basic sequence libraries should reside in the /e directory of the eVC. They should be loaded by the top
file so that the basic sequences are always available. A basic library name should reflect its purpose. For
example, the vr_axi_master_seq_lib contains sequences like SIMPLE_READ and SIMPLE_WRITE.
extend vr_axi_master_seq_kind: [SIMPLE_WRITE, SIMPLE_READ];

Additional eVC Libraries


Additional sequence libraries may be provided by the eVC developer or by higher level verification
environments. These may include:

Configuration sequences to set up the DUT for normal operation


Sequences to drive normal or erroneous traffic to the DUT
3-28

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System Level


Stimulus Generation

Register sequences to exercise the DUT registers


Virtual sequences to activate multiple ports concurrently
These additional sequence libraries should reside in the /examples/seq_lib directory of the eVC.
SVE-specific sequence libraries should reside in the /*_sve/seq_lib directory of a module or system
eVC.
These libraries are imported by the various test files rather than being imported automatically from the
eVC top file. Each test file imports only the necessary sequence libraries, thus minimizing the
performance penalty.

User-Defined Libraries
Additional sequence libraries are developed and maintained end users in their verification environment
under their /seq_lib directory.

3.8.1.2

Generation Tips

Random generation is a very powerful tool for productivity (reducing the manual work of configuring
the environment or DUT and creating stimulus) and improved quality (hunting for bugs in areas that are
hard to foresee). However, excess use of generation might result in scalability problems. When building
a large verification environment, consider carefully how to avoid unnecessarily complex generation that
might slow down the entire simulation.
The following tips show how to avoid some common pitfalls related to large verification environments.
The overall effect depends on the size and complexity of the DUT.
Avoid temporal expressions in sequence items
Defining events or temporal expressions in sequences and sequence items is a major obstacle for
scalability. These structs are never collected by the garbage collection system, causing gradual slow
down of the simulation. Instead of defining an event in a sequence, you can define it in the driver and
access it as driver.event from within the sequence.
If temporal expressions or events are used in sequence items, they should be terminated using
struct.quit() once the item is fully processed. When appropriate you can use the auto_quit() method of
a sequence or sequence item. This will automatically quit the struct when the sequence mechanism does
not need it any more.
extend any_sequence_item {
auto_quit() : bool is only {
return TRUE;
};
};

System Verification Methodology

Version 2.0 Beta 1

3-29

From Module Level to System Level


Stimulus Generation

Note If a sequence item is used by the verification environment after item_done, then automatic
quitting is not applicable. The program must issue quit() when done.
Simplify complex sequences by limiting the capabilities
Sequences and sequence items might require complex generation. Performance can often be improved
by simplifying the generation, while giving up some of the randomization that might not be necessary on
the system level.
In the following example, the ONLY_OK sequence simplifies the generation of the slave response. In
the general case, the response is a random list of SPLIT/RETRY terminated by OK. The ONLY_OK
sequence always generates a single OK response. You can run many useful system tests using this
simplified sequence, assuming that the full capabilities of the slave response were already exercised on
the module level.
extend SIMPLE_RESPONSE vr_ahb_slave_seq {
!resp_seq: ONLY_OK vr_ahb_slave_driven_burst_response;
body() @driver.clock is {
do resp_seq;
};
};

Simplify the generation of complex sequences


In extreme cases, it pays to apply the do statement to a pregenerated item. In the following example, the
write() method generates a complex sequence item that has numerous transfers. The naive
implementation is as follows:
write(address: vr_ahb_address, data: list of vr_ahb_data, b_kind:
vr_ahb_burst_kind, size: vr_ahb_transfer_size) @driver.clock is {
do burst keeping {
.kind == b_kind;
.direction == WRITE;
.first_address == address;
.data == data;
.size == size;
.transmit_delay == 0;
.delay == 0;
};
};

A more efficient way of implementing the write() method is to create the burst (using new) and then
constrain the do action to use the pregenerated struct:
write(address: vr_ahb_address, data: list of vr_ahb_data, b_kind:
vr_ahb_burst_kind, size: vr_ahb_transfer_size) @driver.clock is {
var new_burst := new vr_ahb_master_driven_burst with {
.kind = b_kind;

3-30

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System Level


Stimulus Generation

.direction = WRITE;
.first_address = address;
.data = data;
.size = size;
.transmit_delay = 0;
.delay = 0;
};
for i from 0 to size - 1 {
var trans := new vr_ahb_master_driven_transfer with {
.size = new_burst.size;
.direction = new_burst.direction;
.kind = (i == 0 ? NONSEQ : SEQ);
};
new_burst.transfers.add(trans);
};
do burst keeping {it == new_burst};
};

The second solution is clearly more complicated. Only apply it in cases where the profiler indicates that
the simple implementation is too expensive.
Minimize the number of generation roles
Every do statement creates a new generation role. By minimizing the generation roles, you can make
code more efficient. You can do that by encapsulating do operations in for loops, methods, or sequences.
Assume a device with four ports and multiple registers controlling each port. The simple way to
initialize the device would be as follows (where write_reg is a macro hiding a do statement):
extend vr_ad_sequence_kind : [INIT_PORTS];
extend INIT_PORTS vr_ad_sequence {
!port_reg : PORT_REG vr_ad_reg;
body() @driver.clock is {
write_reg port_reg {.port_num == 1;
write_reg port_reg {.port_num == 2;
write_reg port_reg {.port_num == 3;
write_reg port_reg {.port_num == 4;
};
};

.enable
.enable
.enable
.enable

=
=
=
=

TRUE};
TRUE};
TRUE};
TRUE};

A more efficient way to write the above sequence is to use a for loop, having a single role instead of the
four roles in the previous implementation:
extend vr_ad_sequence_kind : [INIT_PORTS];
extend INIT_PORTS vr_ad_sequence {
!port_reg : PORT_REG vr_ad_reg;
body() @driver.clock is {

System Verification Methodology

Version 2.0 Beta 1

3-31

From Module Level to System Level


Checking

for i from 1 to 4 {
write_reg port_reg {.port_num == i; .enable = TRUE};
};
};
};

Note gen has a similar effect to do.This suggestion applies to gen as well.

3.8.2

Checking

Most eVCs have a large set of checks prepared for various verification tasks. Depending on the nature of
the DUT, some of the checks might be irrelevant for certain tasks. For example, when the DUT is a
slave, the master checks in the eVC are not useful.

3.8.2.1

Preparing the eVC for Scalability

Every eVC agent must have a has_checks field that is set by default to FALSE for active agents and
TRUE for passive agents. A corresponding has_checks field in the monitor inherits the value from the
agent.
has_checks: bool;
keep active_passive == ACTIVE => soft has_checks == FALSE;
keep active_passive == PASSIVE => soft has_checks == TRUE;
keep monitor.has_checks == read_only(has_checks);

All checks in an eVC should be implemented under the has_checks subtype of the monitor.
extend has_checks MASTER vr_axi_agent_monitor {
...

3.8.2.2

Grouping Checks

The eVC developer should identify the checks needed for each verification goal. If the checks can be
grouped in a logical way, each group should have its own has_*_checks flag so that each group can be
turned off separately. For example, you could implement signal checks in a separate group under
has_signal_checks. Other groups could include data checks, latency checks, power checks, and so on.
In such cases, all subgroups are soft constrained to the main has_checks flag.
keep soft has_signal_checks == read_only(has_checks);

Checks can also be turned off individually using the set checks command:
set check @module IGNORE

3-32

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System Level


Coverage

3.8.2.3

Determining the Appropriate Tradeoff

The final decision as to which checks are active in system verification must be left to the end user.
Within the same eVC, some agents might be internal to the system (and hence their protocol checking
was already verified in various subsystems) while other agents represent external devices (and hence
require full protocol checking even at the system level).
Module and system eVCs have their own checkers responsible for system-level checking, such as
connectivity and interoperability. Implement these checks under has_checks but keep them active
during system verification. They can be turned off later, for example, for HW/SW co-verification.

3.8.3

Coverage

Coverage is handled similar to checking. While it serves an important role during module verification,
some coverage may be traded off for performance during system-level verification.
All coverage definitions and related code should be implemented under a has_coverage subtype of the
monitor. The value is inherited from a similar has_coverage flag in the agent.
unit vr_axi_slave like vr_axi_agent {
has_coverage: bool;
keep active_passive == ACTIVE => soft has_coverage == FALSE;
keep active_passive == PASSIVE => soft has_coverage == TRUE;
keep monitor.has_coverage == read_only(has_coverage);
}

In addition, when checking is turned off, coverage should be turned off as well. It makes no sense to
collect coverage when checking is off.

3.8.3.1

Grouping Coverage

As in checking, coverage definitions can also be structured in logical groups, under various
has_*_coverage flags, like has_whitebox_coverage or has_error_coverage. Error coverage and
whitebox coverage are important at the module level. On the other hand, for system-level verification,
they could create holes in the coverage. There might be no simple way to create all error cases or
activate all internal states in a specific system. Therefore, this kind of coverage should be implemented
under special subtypes so that it can be disabled at the system level.
All subgroups should be soft-constrained to the main has_checks flag. For example:
keep soft has_whitebox_coverage == read_only(has_coverage);

As a general rule, coverage subgroups should match the checking subgroups. Whenever a checking
subgroup is turned off, the corresponding coverage subgroup should be turned off as well.
keep soft has_whitebox_coverage == has_whitebox_checks;
System Verification Methodology

Version 2.0 Beta 1

3-33

From Module Level to System Level


Messages

Individual coverage groups can be disabled using:


covers.set_cover("packet.*", FALSE);

3.8.3.2

Determining the Appropriate Tradeoff

System verification has its own specific coverage goals implemented in the SVE and various subsystem
eVCs. These include connectivity and interoperability, which must be active during system verification,
but can be turned off, for example, for HW/SW co-verification.

3.8.3.3

Minimizing Overhead with the Coverage API

The coverage API contains options to turn off coverage groups that are not appropriate at the system
level. For example:
cover cover_group using also no_collect = TRUE;

3.8.4

Messages

eVCs typically produce a lot of useful information for module-level verification. Some of that
information might be redundant in system verification.
Messages and message loggers that are not activated require minimal or no resources. eVC developers
should leave all message loggers in their default state to avoid an unnecessary performance penalty.
Loggers and messages in a large SoC environment should be activated only for debugging purposes.
Even then, they should be activated selectively, focusing on the area of interest.
The message facility in eRM lets you improve performance by turning off unnecessary messages. You
can lower message verbosity either globally (by controlling all messages from the system logger) or
selectively (by controlling the loggers in the env unit of each eVC). In addition, the message facility
provides more selective control over messages, based on the verification environment architecture,
message tags, and so on.

3.8.5

eVC-specific Solutions

eVC performance can typically be improved by profiling it for a specific DUT and tweaking the eVC
capabilities. Often, there is a tradeoff between high performance versus full flexibility and
debuggability. Performance can be improved by giving up some of the capabilities. This section
describes some performance improvements that eVC developers might provide.

3-34

Version 2.0 Beta 1

System Verification Methodology

From Module Level to System Level


eVC-specific Solutions

3.8.5.1

Minimizing Context Switching

The BFM and monitor typically access the signals with a high frequency, causing a large number of
context switches between Specman and the simulator. This can be significant in serial protocols, where
context switching is at the bit level rather than the packet level.
Implementing a small layer of the BFM and monitor in HDL can significantly decrease context
switching and thus improve performance. eVCs providing such an HDL layer as an optional component
let users choose between better performance and better visibility.

3.8.5.2

Sharing Monitors

In some environments, performance can be improved by having multiple components share a monitor.
In particular, in point-to-point interfaces, both agents representing an endpoint can use the same monitor.
In addition, when there are multiple agents on a bus, you can use a single bus monitor for all of the bus
agents rather than a separate monitor for each bus agent.

3.8.5.3

Implementing Deterministic Behavior

In some simple cases, the eVC developer can provide a deterministic alternative to the general-purpose,
sequence-based solution. A typical example would be a preprogrammed arbiter that performs a
predefined arbitration algorithm. Such an arbiter can be very efficient, having no need for sequence
generation. The cost is a loss of control by the sequence mechanism.

3.8.5.4

Optimizing Sequence Drivers

Typically, the clock in virtual sequence drivers is tied to sys.any. In some cases, this can cause an
unnecessary performance loss. In such cases, the clock can be emitted only when needed, thus
improving the performance of the driver.
In the following layering example, a low-level sequence obtains the next item from a higher-level driver.
Instead of running the clock of the high-level driver on sys.any, the low-level sequence emits the clock
in pre_do().
pre_do(is_item:bool)@sys.any is {
emit driver.upper_driver.clock; // Emit the clock for the
// high-level driver
upper_data = driver.upper_driver.get_next_item().data;
emit driver.upper_driver.item_done;
};

System Verification Methodology

Version 2.0 Beta 1

3-35

From Module Level to System Level


eVC-specific Solutions

3-36

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model

This chapter contains the following sections:

Introduction to the Register and Memory Model on page 4-1


Overview of the Register and Memory Package on page 4-2
Architecture of the Register Model on page 4-7
Integration of the Register Model on page 4-17
Creating Register Sequences on page 4-21
Using the Register Features on page 4-30
Sparse Memory on page 4-50
Register and Memory Data Structures on page 4-61
Address Management (Sets) on page 4-96
Registers Visualization on page 4-104
Register and Memory Commands on page 4-110

4.1

Introduction to the Register and Memory Model

The register and memory package (vr_ad) models the behavior of memory and registers. It contains
some built-in mechanisms with predefined types for efficient modeling.
The package addresses three independent aspects: address management, register modeling, and memory
modeling.
This section contains:

Main Features of the Register and Memory Package on page 4-2


System Verification Methodology

Version 2.0 Beta 1

4-1

The Register and Memory Model


Main Features of the Register and Memory Package

Naming Conventions on page 4-2


Compilation on page 4-2

4.1.1

Main Features of the Register and Memory Package

The main features supported in this package are:


Modeling of registers,
register files, and memory
maps

Defining register types


Creating a hierarchy of addressable items
Defining coverage for registers
Maintaining consistency of the register model
Modeling of sparse memory

Accessing registers using


sequences

Using layering for protocol-independent access


Accessing specific registers
Accessing random registers
Modifying a register field
Backdoor accessing
Indirect accessing

Address management

Allocating/deallocating addresses for registers and register files

4.1.2

Naming Conventions

Registers are entities in the global name space. When a system is created out of multiple subsystems,
register names might collide. Therefore, Cadence recommends using a unique prefix for all addressable
items names, following the unique naming conventions of eRM.

4.1.3

Compilation

The register and memory package (vr_ad) includes some macro definitions. Therefore, if you want to
compile the package with user code that relies on the package, you must compile the package first and
then compile the user code on top of the package.

4.2

Overview of the Register and Memory Package

This section presents an overview of the register and memory package components and the integration
of the package with an existing environment. For this purpose, we use the simple ex_c_bus environment
(see Figure 4-1). More complex examples can be found in the remaining sections. The following
components are introduced in addition to the basic eRM elements (env, agents, sequence drivers):
4-2

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Overview of the Register and Memory Package

Register File Represents DUT agent registers. It contains a list of consecutive registers.
Address Map Represents the address space. It maps the register files and the memory blocks (if
any) in the address space, and it contains references to them. In a very simple environment with only
one register file, an address map may seem redundant. Address maps gain importance in environments
with multiple register files.

Register Sequence Driver (RSD) A dedicated sequence driver for register operations. The
functionality of the RSD resembles that of a virtual sequence driver.

Figure 4-1

Registers in the ex_c_bus Environment

ex_c_bus env
Register
File

RSD
Address
Map
Active Master

Passive Slave

SD

Mon

BFM

System Verification Methodology

Monitor

Version 2.0 Beta 1

4-3

The Register and Memory Model


Overview of the Register and Memory Package

Figure 4-2 shows the connection between the various elements of the register and memory model.

Figure 4-2

Memory

Address Map
Address Map

Register File
Register

Memory
block

Register

Static
information

For a detailed description of the data structures, see Register and Memory Data Structures on page
4-61.

To create and integrate the register model into your ex_c_bus environment:
1.

Define a register file, and reset all registers.


For example, you could define a register file named XCORE with a size of 256 bytes and reset all
registers as follows:
extend vr_ad_reg_file_kind : [XCORE];
extend XCORE vr_ad_reg_file {
keep size == 256;
post_generate() is also {
reset();
};
};

For details on defining a register file, see Defining a Register File on page 4-9.
2.

Define the registers using the reg_def macro.


For example, you could define the EX_REG_TX_DATA register and automatically add it at offset
0 of XCORE as follows:
//
NAME
REGFILE ADDR
reg_def EX_REG_TX_DATA XCORE 8h00 {
//
name : type
: mask : reset value
reg_fld data : uint(bits:8) : RW
: 0;
};

For details on defining registers, see Defining Registers with the reg_def Macro on page 4-9.
4-4

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Overview of the Register and Memory Package

3.

Instantiate the new register file under a unit in your environment.


For example, you could instantiate the XCORE register file under the ex_c_bus env as follows:
extend ex_c_bus_env {
reg_file : XCORE vr_ad_reg_file;
};

For details on where and how to instantiate the register file, see Instantiating the Register File in the
Architecture on page 4-15.

4.

Instantiate an address map and a register sequence driver.


The register sequence driver must be linked to the address map and it must have a default BFM
sequence driver.
For example, you could use the ex_c_bus env to instantiate both the address map and the register
sequence driver. You could use the BFM sequence driver of masters[0] as the default driver for the
register sequence driver (RSD).
extend ex_c_bus_env {
addr_map : vr_ad_map;
rsd: vr_ad_sequence_driver is instance;
keep rsd.addr_map == value(addr_map);
keep rsd.default_bfm_sd == masters[0].driver;
};

For details on instantiating the address map and the RSD, see Instantiating the Address Map and the
RSD on page 4-15.
5.

Allocate an address space for the register file by adding it to the address map at the desired offset.
For example, you could allocate addresses starting from 0x0 as follows:
extend ex_c_bus_env {
post_generate() is also {
addr_map.add_with_offset(0,reg_file);
};
};

For details on adding the register file to the address map, see Adding the Register File to the
Address Map on page 4-15.
6.

Implement the eVC BFM sequence drivers vr_ad_execute_op() method, which takes the contents
of the register operation and executes it.
This is necessary for layering the register sequences on top of the eVC. For example, your
implementation of vr_ad_execute_op might use the read() and write() sequence methods as
follows:
extend ex_c_bus_driver {

System Verification Methodology

Version 2.0 Beta 1

4-5

The Register and Memory Model


Overview of the Register and Memory Package

vr_ad_execute_op(op_item : vr_ad_operation) : list of byte @clock is {


if op_item.direction == WRITE {
sequence.write(op_item.address, reg_op.get_data());
} else {
result = pack(packing.low,sequence.read(op_item.address));
};
};

For details on integrating the register sequence driver with an eVC agent, see Integrating the RSD
with the BFM Sequence Driver on page 4-18.
7.

Bind the eVC monitor to the address map for updating the register model and collecting coverage.
For example, you could use the transfer_end event detected by the monitor. The update() method is
called for write operations. The compare_and_update() method is called for read operations.
extend vr_xbus_bus_monitor_u {
on transfer_end {
if transfer.read_write == WRITE {
get_enclosing_unit(vr_xbus_env_u).addr_map.update(
transfer.addr,pack(packing.low,transfer.data),{});
} else {
compute get_enclosing_unit(vr_xbus_env_u).\
addr_map.compare_and_update(transfer.addr,
pack(packing.low,transfer.data));
};
};
};

For details on updating the registers from a monitor, see Updating the Register Model Using an eVC
Monitor on page 4-20.
You can now create register sequences and access the registers using the write_reg and read_reg
macros. For example:
extend vr_ad_sequence_kind: [MY_SEQ];
extend MY_SEQ vr_ad_sequence {
!tx_data : EX_REG_TX_DATA vr_ad_reg;
body() @driver.clock is only {
write_reg tx_data;
read_reg tx_data;
};
};

For details on accessing the registers, see write_reg and read_reg Macros on page 4-24.

4-6

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Architecture of the Register Model

4.3

Architecture of the Register Model

The next two sections use the Cadence XCore environment (vr_xcore) to demonstrate an integration of
the register model. The environment contains two instances of XCore, controlled from an XBus master
by writing to the XCore registers. As a result of the register operations, the XCore performs read or write
transactions on the XSerial port. Figure 4-3 shows the register and address management aspect layered
on top of the architecture, including the address map, register file, and register sequence driver.
Figure 4-3

Registers in the eRM Architecture

Typically each XCore is represented by a module eVC. The best place to instantiate the register file
is in the module eVC. If your environment does not have a module eVC, you can instantiate the
register file in the XBus env or in the PASSIVE slave agent.

The XBus passive slave has a reference to the register file instantiated in the module eVC.
The XBus env has the address map and the register sequence driver (RSD).
The RSD is layered on top of the BFM sequence driver.
To create the register model:
1.

Define a register file.

2.

Define the register types and optionally add instances of those registers into a register file (using the
reg_def macro).

System Verification Methodology

Version 2.0 Beta 1

4-7

The Register and Memory Model


Defining the Register Address and Data Width

3.

Instantiate the register file in the architecture (for example, in an agent) with no absolute address
assigned yet.

4.

Instantiate the address map and the register sequence driver in the environment.

5.

Add the register file to the address map (setting the absolute base address for the register file). This
can be done at runtime or at post-generate.

This section contains:

Defining the Register Address and Data Width on page 4-8


Defining a Register File on page 4-9
Defining Registers with the reg_def Macro on page 4-9
Instantiating the Register File in the Architecture on page 4-15
Instantiating the Address Map and the RSD on page 4-15
Adding the Register File to the Address Map on page 4-15

4.3.1

Defining the Register Address and Data Width

The address and data fields are unsigned integers with default size defined as follows:
define
define

VR_AD_ADDRESS_WIDTH
VR_AD_DATA_WIDTH

32;
32;

type vr_ad_addr_t: uint(bits:VR_AD_ADDRESS_WIDTH);


type vr_ad_data_t: uint(bits:VR_AD_DATA_WIDTH);

If your address or data width exceeds these default settings, you must change them to the highest value
to be used in your verification environment. As these statements define the actual types used in the
model, they must be set before the vr_ad package is loaded. For example, if your largest registers are 64
bits wide, you must define VR_AD_DATA_WIDTH to be 64, and your configuration file must start
with the following lines:
define VR_AD_DATA_WIDTH
import vr_ad/e/vr_ad_top;

64;

If your address space is a 64 bits wide, you must define VR_AD_ADDR_WIDTH to be 64, and your
configuration file must start with:
define VR_AD_ADDRESS_WIDTH
import vr_ad/e/vr_ad_top;

4-8

64;

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Defining a Register File

4.3.2

Defining a Register File

To define a register file:

Define the new kind of register file with its size, and reset all registers.
For example:
extend vr_ad_reg_file_kind : [XCORE];
extend XCORE vr_ad_reg_file {
keep size == 256;
post_generate() is also {
reset();
};
};

The size is in terms of how many addresses it occupies (and not the number of registers it contains). This
register file occupies 256 consecutive address entries when inserted into the memory map. By default
each address entry is a byte size, but you can change that. (See Adding the Register File to the Address
Map on page 4-15 and Appendix 4 The Register and Memory Model.)

4.3.3

Defining Registers with the reg_def Macro

The reg_def macro is provided for easy definition and instantiation of the registers. The macro defines
the register type and optionally instantiates it under a register file. If the register has a single instance in
the verification environment, provide the register file name and offset for this instance. If multiple
instances will be created, omit the register file name and offset and create the instances as described in
Defining Multiple Instances of a Register Type on page 4-12.
This section contains:

reg_def Macro on page 4-10


Defining a Register Instance on page 4-11
Defining Multiple Instances of a Register Type on page 4-12
reg_list Macro on page 4-13
Mirroring Registers on page 4-13
Defining Coverage of Fields on page 4-14

System Verification Methodology

Version 2.0 Beta 1

4-9

The Register and Memory Model


Defining Registers with the reg_def Macro

4.3.3.1

reg_def Macro

Purpose
Define a register type with the write mask and reset value defined for each register field.

Syntax
reg_def reg-name [register-file-name offset] {
reg_fld field-name : field-type : field-mask : field-reset-value [: cov];
};
Syntax Example
reg_def EX_REGS_TX_MODE XCORE 0x100 {
reg_fld dest
: uint(bits:2)
: RW
reg_fld frame_kind : [DATA,MESSAGE,A,B](bits:2) : RW
};

:
:

0x0 : cov;
DATA : cov;

Parameters
reg_name

Register nameMust follow eRM naming conventions and use a company prefix

register-file-name

(Optional) Name of the register file where the register is instantiated

offset

(Optional) Offset of the register in the register file

field-name

Register field name

field-type

Register field type

field-mask

Field mask (see Register Field Attributes on page 4-49)

field-reset-value

Field value to be set on reset

cov

(Optional) Add coverage for the field

Notes
The keyword reg_fld automatically defines the register field as a physical field (%).
The reset value must be a legal value for the type of the declared field. For example, if the field is
defined as Boolean, the reset value must be either TRUE or FALSE. Fields that are structs or lists
should get a number for the entire field.

4-10

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Defining Registers with the reg_def Macro

You can specify only the field name and type. In that case, the default mask is RW, and the reset value
is 0.

4.3.3.2

Defining a Register Instance

To define a register instance:

Use the reg_def macro.


Example
You could create an EX_REGS_TX_MODE register with several fields and instantiate a copy of it
under the XCORE register file as follows:
//
NAME
FILE
OFFSET
reg_def EX_REGS_TX_MODE XCORE
8h03 {
// Custom Fields
reg_fld dest
: uint(bits:2)
: RW : 0
: cov;
reg_fld frame_kind : [DATA,MESSAGE,A,B](bits:2) : RW : DATA : cov;
reg_fld resv
: uint(bits:4)
: RW : 0 ;
};

The above code is translated by the macro into:


extend vr_ad_reg_kind : [EX_REGS_TX_MODE];
extend EX_REGS_TX_MODE vr_ad_reg {
%dest : uint(bits:2);
%frame_kind : [DATA,MESSAGE,A,B](bits:2);
%resv : uint(bits:4);
cover reg_access (kind == EX_REGS_TX_MODE) is also {
item ex_reg_tx_mode_dest = dest;
item ex_regs_tx_mode_frame_kind = frame kind;
};
update_attributes() is also {
// This method is called automatically. It contains internal code
// to store the static parameters in the static_info struct
};
};
extend XCORE vr_ad_reg_file {
%ex_regs_tx_mode : EX_REGS_TX_MODE vr_ad_reg;
post_generate() is also {
add_with_offset(8'h3,ex_regs_tx_mode);
};
};

System Verification Methodology

Version 2.0 Beta 1

4-11

The Register and Memory Model


Defining Registers with the reg_def Macro

The default field order of a register is from high bit position to low bit position. For example, the field
order of the EX_REGS_TX_MODE register is:
extend EX_REGS_TX_MODE vr_ad_reg {
%dest
: uint(bits:2);
%frame_kind : [DATA,MESSAGE,A,B](bits:2);
%resv
: uint(bits:4);
};

// Bits [7:6]
// Bits [5:4]
// Bits [3:0]

For instructions on changing the default field order, see Changing the Register Field Order on page
4-44.
Note The name of the register that is automatically added to the register file is the register kind in lower
case. So, with the above example, you can directly access the register xcore_reg_file.ex_regs_tx_mode.

See Also
Fields and Methods of vr_ad_reg on page 4-75

4.3.3.3

Defining Multiple Instances of a Register Type

To define multiple instances of a register type:


1.

Create the register type using the reg_def macro, but do not specify a register file name or offset.
For example:
//
NAME
reg_def EX_REGS_PORT_CONTROL {
reg_fld control
: port_control_kind_t;
};

2.

Extend the register file to add instances of the register type using the add_with_offset() method.
For example:
extend vr_ad_reg_file_kind : [PORTS];
extend PORTS vr_ad_reg_file {
port_regs[4] : list of EX_REGS_PORT_CONTROL vr_ad_reg;
post_generate() is also {
for each (p) in port_regs {
add_with_offset(index*4, p);
};
};
};

Note You can also use the reg_list macro here (see reg_list Macro on page 4-13).

4-12

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Defining Registers with the reg_def Macro

4.3.3.4

reg_list Macro

Purpose
Instantiate a register list inside a register file, and automatically call add_with_offset() for each register
in the register list.

Syntax
reg_list list-name[list-size] of reg-kind at offset;
Syntax Example
extend EX_FILE vr_ad_reg_file {
reg_list regs[128] of EX_REG at 0x1000;
};

Parameters
list-name

Name of the created list field

list-size

Size of the created list

reg-kind

Kind of registers in the list

offset

Starting address from which the registers are subsequently added

Notes
The registers are not generated but rather created by a new action (for performance reasons).
Cadence recommends using this macro when you must generate a large list of registers.

4.3.3.5

Mirroring Registers

Occasionally, a register is mapped in multiple locations in the register file. In such cases, the register can
be accessed via multiple addresses.
To implement mirroring of registers:

Use the add_with_offset() method.


For example, you could define EX_REG_TX_MODE register at address 0x3 of the XCORE register file
and mirror the register at address 0x10 as follows:

System Verification Methodology

Version 2.0 Beta 1

4-13

The Register and Memory Model


Defining Registers with the reg_def Macro

//
NAME
FILE
OFFSET
reg_def EX_REGS_TX_MODE XCORE 8h03 {
// Custom Fields
reg_fld dest
: uint(bits:2)
: RW : 0 : cov;
reg_fld frame_kind : [DATA,MESSAGE,A,B](bits:2) : RW : A : cov;
reg_fld resv
: uint(bits:4)
: RW : 0 ;
};
// Add Mirror address
extend XCORE vr_ad_reg_file {
post_generate() is also {
add_with_offset(0x10,ex_regs_tx_mode);
// Note: ex_regs_tx_mode is automatically defined by the
// "reg_def" macro as a field of the XCORE register file.
};
};

See Also
add_with_offset() on page 4-79

4.3.3.6

Defining Coverage of Fields

Coverage per register field can be defined automatically by adding the attribute cov to the reg_fld
definition in the reg_def macro. This adds a coverage item of the field to the reg_access coverage
group.

Example
The following code would be automatically created by the register definition in the example found in
Mirroring Registers on page 4-13.
extend EX_REGS_TX_MODE vr_ad_reg {
cover reg_access(kind == EX_REGS_TX_MODE) is also {
item ex_regs_tx_mode_dest;
item ex_regs_tx_mode_frame_kind;
};
};

See Also
Coverage on page 4-33

4-14

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Instantiating the Register File in the Architecture

4.3.4

Instantiating the Register File in the Architecture

The register file represents the DUT agent registers. Instantiate it in the module eVC or in the passive
agent of the interface eVC.
To instantiate the register file in a passive agent:

Extend the relevant agent with the required instances.


For example:
extend PASSIVE SLAVE vr_xbus_agent_u {
reg_file : XCORE vr_ad_reg_file;
};

4.3.5

Instantiating the Address Map and the RSD

The address map represents the entire address space. It contains pointers to all register files in the
address space. It is used as a reference model. Instantiate it in the env corresponding to the address
space.
If you want to use register sequences, an RSD must also be instantiated at the same place and connected
to the address map. The RSD gets the information it requires for accessing registers from the address
map. The RSD should also be connected to a default BFM SD (for example, an xbus sequence driver) so
that it can perform the register operation according to the specific bus protocol.
To instantiate the address map and the RSD:

Extend the relevant env with the required address map and RSD instances.
For example:
extend vr_xbus_env_u {
addr_map : vr_ad_map;
reg_driver: vr_ad_sequence_driver is instance;
keep reg_driver.addr_map == value(addr_map);
keep reg_driver.default_bfm_sd == active_masters[0].driver;
};

4.3.6

Adding the Register File to the Address Map

The vr_ad_map.add_with_offset() method allocates address space for the register file and adds it to the
address map. Typically this is done in the post_generate() phase, but it can also be done during
simulation.

System Verification Methodology

Version 2.0 Beta 1

4-15

The Register and Memory Model


Adding the Register File to the Address Map

To add the register file to the address map:

Use the add_with_offset() with the desired offset and register file.
For example:
extend vr_xbus_env_u {
post_generate() is also {
var reg_file = passive_slaves[0].
as_a(DUT_XCORE_0 vr_xbus_agent_u).reg_file;
addr_map.add_with_offset(0,reg_file);
};
};

See Also
add_with_offset() on page 4-83

4.3.6.1

Mirroring Register Files

Occasionally, a register file is mapped in multiple locations in the address space. In such cases, the
register file can be accessed via multiple addresses.
To implement mirroring of register files:

Use the add_with_offset() method to allocate another address space for the register file.
For example, you could define an XCORE register file for access via addresses 0x100 and 0x1000 as
follows:
extend vr_xbus_env_u {
reg_file : XCORE vr_ad_reg_file;
post_generate() is also {
addr_map.add_with_offset(0x100,reg_file);
addr_map.add_with_offset(0x1000,reg_file);
};
};

See Also
add_with_offset() on page 4-83

4-16

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Integration of the Register Model

4.4

Integration of the Register Model

To integrate the register model into an existing environment:


1.

Connect the eVC monitor to the address map of the register model.
The monitor identifies DUT activity. For WRITE transactions, it updates the register model via the
update() method. For READ transactions it checks the received data via the
compare_and_update() method.

2.

Implement the vr_ad_execute_op() method for your eVC SD.


The vr_ad_execute_op() method lets you layer the RSD on top of the BFM SD.
Note This step is needed only when the register and memory package drives registers.

Figure 4-1 describes the typical flow of a register operation.

Figure 4-1

Integrating the Register Model

System Verification Methodology

Version 2.0 Beta 1

4-17

The Register and Memory Model


Integrating the RSD with the BFM Sequence Driver

The register operation flow can be divided into two parts as follows:
Driving Registers

Monitoring

1.

The RSD activates the appropriate BFM sequence driver by calling its
vr_ad_execute_op() method.

2.

The BFM sequence driver executes the operation using the associated
BFM.

3.

The registers in the DUT XCore1 are updated.

4.

The monitor in the PASSIVE slave picks up transactions on the bus.

5.

The monitor notifies the address map by calling the update() method.

6.

The address map updates the registers in the register file.

This section contains:

Integrating the RSD with the BFM Sequence Driver on page 4-18 (Steps 1-3)
Updating the Register Model Using an eVC Monitor on page 4-20 (Steps 4-6)

4.4.1

Integrating the RSD with the BFM Sequence Driver

Register sequences are executed by the register sequence driver (RSD). When a do action is executed,
the RSD activates the destination BFM sequence driver by calling its vr_ad_execute_op() method and
forwarding the register operation to it. The vr_ad_execute_op() method must be implemented by the
eVC developer. It converts the protocol-independent operation into eVC-specific bus transactions.
vr_ad_execute_op(operation : vr_ad_operation) : list of byte @clock;

The information needed for creating eVC-specific register access is available through the operation
parameter. The returned value of the method is a list of byte, used only for READ operations.
Table 4-1 describes the information that is typically required from the operation parameter.

Table 4-1

Information Available from the operation Parameter

Field/Method

Description

address

Address of the target bus transaction

direction

Direction of the target bus transaction

addr_space

Address space identifier (required only if you use it in the register


sequences)

byte_enable

Byte enable (required only if you use it in the register sequences)

4-18

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Integrating the RSD with the BFM Sequence Driver

Table 4-1

Information Available from the operation Parameter (continued)

Field/Method

Description

get_data()

Data of the operation in a numeric form

get_lob_data()

Data of the operation in a list of byte form

get_num_of_bytes()

Number of bytes in data

get_reg()

Returns the register (only for REG operations)

Example
You could implement the vr_ad_execute_op() method for the Cadence XBus eVC as follows:
extend vr_xbus_master_seq_kind : [REG_SEQ]
extend vr_xbus_master_driver_u {
// This example uses a dedicated sequence instead of MAIN for executing
// the register operation
reg_seq : REG_SEQ vr_xbus_master_seq;
keep reg_seq.driver == me;
vr_ad_execute_op(op: vr_ad_operation): list of byte @clock is {
if op.direction == WRITE {
reg_seq.write(op.get_num_of_bytes(),data_size_in_byte,
op.address, op.get_data())
} else {
result = pack(packing.low,
reg_seq.read(op.get_num_of_bytes(), op.address));
};
};
};

Note The above implementation uses the read and write methods of the native sequence. The
implementation of these methods is recommended by eRM. They are described in the section on
Enhancing the User Interface of the e Reuse Methodology (eRM) Developer Manual.
The read() and write() methods of the Cadence XBus eVC sequences are implemented as follows:
extend vr_xbus_master_sequence {
!trans: MASTER vr_xbus_trans_s;
// This method performs one write transfer on the bus.
write(size : uint, addr : uint(bits:16),
data : uint(bits:64)) @driver.clock is {
assert size in [1, 2, 4, 8];
do trans keeping {
.addr == addr;
.read_write == WRITE;
System Verification Methodology

Version 2.0 Beta 1

4-19

The Register and Memory Model


Updating the Register Model Using an eVC Monitor

.size == size;
.data == pack(packing.low, data[size*8-1:0]);
};
};
// This method performs one read transfer on the bus.
read(size : uint, addr : uint(bits:16)) :
uint(bits:64) @driver.clock is {
assert size in [1, 2, 4, 8];
do trans keeping {
.addr == addr;
.read_write == READ;
.size == size };
if trans != NULL {
result = pack(packing.low, trans.data);
} else {
out("trans is NULL");
};
};
};

See Also
Cadence XBus documentation

4.4.2

Updating the Register Model Using an eVC Monitor

Typically, the register model is updated by hooking it to a monitor. When the monitor identifies bus
activity, it interprets the activity and updates the register model using the update() method (for WRITE
transactions), and the fetch() or compare_and_update() methods (for READ transactions). The
compare_and_update() method compares the data from the bus with the data stored in the e model and
issues a DUT error for any mismatch. See also Disabling Comparison for Registers on page 4-48.
To implement automatic update of the model:

Hook the model to the eVC monitor.


For example:
extend vr_xbus_bus_monitor_u {
on transfer_end {
if transfer.read_write == WRITE {
env.address_map.update(transfer.addr,%{transfer.data},{});
} else {
compute env.address_map.compare_and_update(
transfer.addr,%{transfer.data});
};
4-20

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Creating Register Sequences

};
};

Notes

Typically monitors contain an event (for example, transaction_end) that can be used for updating.
Monitors should have access to a register file or address map. In the above example, access is achieved
through a reference to the address map in the env. If the register file is local to the agent enclosing
the monitor, the monitor can access it directly.

4.5

Creating Register Sequences

This section contains:

Basic Register Operations on page 4-21


write_reg and read_reg Macros on page 4-24
Creating Deterministic Configuration Sequences on page 4-25
Modifying a Register Field on page 4-26
Writing to a Specific Instance of a Register Type on page 4-27
Accessing Random Registers on page 4-28

4.5.1

Basic Register Operations

The data item that represents a register access is vr_ad_operation. The vr_ad_operation struct carries
specific information about the actual operation to be performed on the register, such as the direction of
the operation, backdoor access, and so on. The same data item serves both register and memory
operations, implemented under different subtypes. The register-specific attributes are defined under the
REG subtype. The memory-specific attributes are defined under the MEM subtype.
The vr_ad_sequence is defined as a sequence of vr_ad_operation.
To perform a simple register access:

Create a new subtype of vr_ad_sequence, and use the predefined op field as the sequence item.
For example, you could access the EX_REGS_TX_MODE register as follows:
extend vr_ad_sequence_kind : [MY_SEQ];
extend MY_SEQ vr_ad_sequence {
body() @driver.clock is only {
do op keeping {
.reg is a EX_REGS_TX_MODE vr_ad_reg;
System Verification Methodology

Version 2.0 Beta 1

4-21

The Register and Memory Model


Basic Register Operations

.direction == WRITE;
};
};
};

As this syntax tends to get complicated when many constraints are needed or when indirect accessing is
required, Cadence recommends using the macros described in write_reg and read_reg Macros on page
4-24. The macros provide a more efficient implementation than the preceding example.
Table 4-2 and Table 4-3 list all controllable fields in vr_ad_operation and vr_ad_sequence. The rest of

this section provides more details on how and when to constrain these fields.
Table 4-2

Fields of vr_ad_operation

Field

When

Description

addr_space: vr_ad_space_kind

Address space identifier. To be used if multiple


address spaces can be accessed from a single bus
(MEMORY / IO).The implementation of
vr_ad_execute_op() must take care of the
addr_space

address: vr_ad_addr_t

Address used by the BFM sequence driver. It is filled


automatically by the register sequence driver, but it
can also be directly constrained

backdoor: bool

TRUE for backdoor access. Default is FALSE. See


Backdoor Operations on page 4-36

byte_enable: vr_ad_data_t

Can be used for specifying byte enables. vr_ad does


not use this value but just passes it on to the
vr_ad_execute_op() method. The implementation of
vr_ad_execute_op() must take care of the
byte_enable

dest_driver:
any_sequence_driver

Destination (BFM) sequence driver for this


operation. To be used if the destination is other than
the rsd.default_bfm_sd

direction: vr_ad_rw_t

Operation direction READ or WRITE

op_mode: vr_ad_op_mode

Operation mode REG or MEM

reg: vr_ad_reg

4-22

REG

The content of REG operation

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Basic Register Operations

Table 4-2

Fields of vr_ad_operation (continued)

Field

When

Description

static_item: vr_ad_base

The addressable item instance to be accessed. To be


used if multiple registers of the same register kind
exist. See Writing to a Specific Instance of a Register
Type on page 4-27

Table 4-3

Fields of vr_ad_sequence

Field

When

Description

addr_space:
vr_ad_space_kind

Address space identifier. To be used if multiple


address spaces can be accessed from a single bus
(MEMORY / IO). The implementation of
vr_ad_execute_op() must take care of the
addr_space

backdoor: bool

TRUE for backdoor operations. See Backdoor


Operations on page 4-36

dest_driver:
any_sequence_driver

Destination (BFM) sequence driver for the sequence.


To be used if the destination is other than the
rsd.default_bfm_sd

indirect_seq: INDIRECT
vr_ad_sequence

Predefined sequence for indirect access

mode: vr_ad_indirect_mode

DIRECT or INDIRECT

op: REG vr_ad_operation

Predefined sequence item for register accesses

prevent_test_done: bool

TRUE to prevent the test from finishing as long as the


sequence is running

reg: vr_ad_reg
static_item: vr_ad_base

INDIRECT

Content of REG operation


The addressable item instance to be accessed. To be
used if multiple registers of the same register kind
exist. See Writing to a Specific Instance of a Register
Type on page 4-27

Note Fields that appears both in vr_ad_operation and in vr_ad_sequence, by default, inherit their
values from their patent sequence.

System Verification Methodology

Version 2.0 Beta 1

4-23

The Register and Memory Model


write_reg and read_reg Macros

4.5.2

write_reg and read_reg Macros

Purpose
Read and write registers.

Syntax
write_reg [{op-block-constraints}]
register-field [{register-block-constraints}]|[val[ue] register-value-exp]
read_reg [op-block-constraints] register-field

Parameters
op-block-constraints

(Optional) Block of constraints for generating the operation fields


(vr_ad_operation)

register-field

Register instance

register-block-constraints

(Optional) Block of constraints for generating the register fields

register-value-exp

(Optional) Value to be written to the entire register

Usage
To use the write_reg and read_reg macros:

Define a field of the appropriate register type, and apply the relevant macro to it.
For example:
extend vr_ad_sequence_kind : [MY_SEQ];
extend MY_SEQ vr_ad_sequence {
!tx_mode : EX_REGS_TX_MODE vr_ad_reg;
body() @driver.clock is only {
write_reg tx_mode {.field1 == 3; ,field2 == 4};
read_reg tx_mode;
};
};

The above code is translated into something like:


extend vr_ad_sequence_kind : [MY_SEQ];
extend MY_SEQ vr_ad_sequence {
4-24

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Creating Deterministic Configuration Sequences

!tx_mode : EX_REGS_TX_MODE vr_ad_reg;


body() @driver.clock is only {
// write_reg tx_mode {.field1 == 3; ,field2 == 4};
gen tx_mode keeping {
.field1 == 3;
.field2 == 4;
};
do op keeping {
.direction == WRITE;
.reg == tx_mode;
};
// read_reg tx_mode;
tx_mode = new;
do op keeping {
.direction == READ;
.reg == tx_mode;
};
};
};

To assign a value for the entire register:

Specify the value for the register in the write_reg value macro.
For example:
extend vr_ad_sequence_kind : [RWR];
extend RWR vr_ad_sequence {
!r1 : R1 vr_ad_reg;
body() @driver.clock is {
read_reg r1;
write_reg r1 value 0xaa;
read_reg r1;
};
};

For an example of using op-block-constraints, see Writing to a Specific Instance of a Register Type on
page 4-27.

4.5.3

Creating Deterministic Configuration Sequences

To create a deterministic configuration sequence:

Use the relevant sequence of read or write register access.

System Verification Methodology

Version 2.0 Beta 1

4-25

The Register and Memory Model


Modifying a Register Field

For example, you could have a configuration sequence that sets the command and base address registers
of the PCI device and reads the status register after a short delay as follows.
extend vr_ad_sequence_kind: [VR_PCI_CONFIG];
extend VR_PCI_CONFIG vr_ad_sequence {
!command_reg : VR_PCI_COMMAND_REG vr_ad_reg;
!base_addr
: VR_PCI_BASE_ADDR vr_ad_reg;
!status
: VR_PCI_STATUS vr_ad_reg;
body() @driver.clock is only {
write_reg command_reg {
.io == FALSE;
.mem == TRUE;
.fast_back_to_back == FALSE
};
write_reg base_addr {
.offset == 0x10;
.mem_kind == MEM;
.base_addr == 0x30000
};
wait [10];
read_reg status;
if status.signalled_serr {
out("signal_serr is enabled in ",status);
};
};
};

4.5.4

Modifying a Register Field

To modify a register field (doing read-modify-write using the value stored in the e model):
1.

Locate the register by address or by kind with get_reg_by_address() or get_reg_by_kind().

2.

Create a copy of the register using the copy() method and cast it to the exact register subtype.

3.

Modify the copy of the register as desired.

4.

Write the copy of the register back using the write_reg macro.

Example
extend MAIN vr_ad_sequence {
!xmode : EX_REGS_TX_MODE vr_ad_reg;
body() @driver.clock is only {
xmode = driver.addr_map.get_reg_by_kind(EX_REGS_TX_MODE).copy()\
.as_a(EX_REGS_TX_MODE vr_ad_reg);

4-26

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Writing to a Specific Instance of a Register Type

xmode.dest = 2;
// Modify field value
write_reg xmode {it == xmode}; // Write back the modified register.
};
};

4.5.5

Writing to a Specific Instance of a Register Type

Occasionally the same register type is used in several places. For example, a device with multiple ports
controlled by identical registers, one for each port, can be modeled using multiple instances of the same
register type. You might want to access a specific register, for example, the register of port number 2.
To write to a specific instance of a register type:

Constrain vr_ad_operation.address to the right address or constrain vr_ad_operation.static_item to


the specific register instance (or the register file in which the register is unique).
Example 1
In the following example, there are two instances of the XCORE register file, located at address 0x100
and 0x200. The static_item field is constrained to a specific instance of the register file. Inside the
register file, the registers can be located uniquely by their type.
extend MAIN vr_ad_sequence {
!tx_data : EX_REGS_TX_DATA vr_ad_reg;
body() @driver.clock is only {
var reg_file1 : XCORE vr_ad_reg_file =
driver.addr_map.get_reg_file_by_address(0x100);
var reg_file2 : XCORE vr_ad_reg_file =
driver.addr_map.get_reg_file_by_address(0x200);
// Access tx_data of reg_file1
write_reg {.static_item == reg_file1} tx_data {.data == 0xaa};
// Access tx_data of reg_file2
write_reg {.static_item == reg_file2} tx_data {.data == 0xbb};
read_reg {.static_item == reg_file1} tx_data;
read_reg {.static_item == reg_file2} tx_data;
};
};

Example 2
In the following example, the register file contains a list of registers of the same type. The register type
is not unique inside the register file. Therefore, you must constrain the address of the operation to the
right register address. Alternatively, you can constrain the static_item field to the specific register
instance.
// Define EX_PORT_CTL register type.
reg_def EX_PORT_CTL {
System Verification Methodology

Version 2.0 Beta 1

4-27

The Register and Memory Model


Accessing Random Registers

reg_fld enable : bool;


reg_fld cmd
: uint(bits:31);
};
// Add multiple instances of EX_PORT_CTL to the register file
extend PORTS vr_ad_reg_file {
port_regs[4] : list of EX_PORT_CTL vr_ad_reg;
post_generate() is also {
for each (p) in port_regs {
add_with_offset(index*4, p);
};
};
};
// Write to specific instances in the register list. When the PORTS
// register file is located at address 0x100, the first register in the
// register file is located at address 0x100, the second register is
// located at address 0x104...
extend MAIN vr_ad_sequence {
port_reg : EX_PORT_CTL vr_ad_reg;
body() @driver.clock is only {
// Access register located at address 0x100
write_reg {.address == 0x100}
port_reg {.enable == TRUE;.cmd == 0xa };
// Access register located at address 0x104
write_reg {.address == 0x104}
port_reg {.enable == FALSE;.cmd == 0xb};
};
};

Note If more than one instance exists and no static_item or address is specified, an error message is
issued.

See Also
write_reg and read_reg Macros on page 4-24
add_with_offset() on page 4-79

4.5.6

Accessing Random Registers

This section contains:

Accessing a Random Register on page 4-29


Accessing Entire Register Files on page 4-30

4-28

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Accessing Random Registers

4.5.6.1

Accessing a Random Register

Accessing a random register can be done using the predefined SIMPLE vr_ad_sequence. With the
SIMPLE sequence you can control the register kind and the data to be written. If you do not constrain
those fields, the kind of the register is generated as one of the register kinds that exist in the address map.
The data is generated randomly. If multiple registers of the same kind exist in the address map, the
SIMPLE sequence accesses one of them. Table 4-4 describes the controllable fields of SIMPLE
vr_ad_sequence.
Table 4-4

SIMPLE vr_ad_sequence Fields

Field

Description

reg_kind : vr_ad_reg_kind

Register kind

reg_addr : vr_ad_addr_t

Register address (not to be used with reg_kind at the same time)

reg_data : vr_ad_data_t

Data to be written to the register

direction : vr_ad_rw_t

READ or WRITE

To access a random register:

Use the predefined SIMPLE sequence.


Example 1
Reading a random register out of the address map registers:
extend MAIN vr_ad_sequence {
!simple : SIMPLE vr_ad_sequence;
body() @driver.clock is only {
do simple keeping {
.direction == READ;
};
};
};

Example 2
Writing 0xaaaa to EX_REGS_TX_MODE register:
extend MAIN vr_ad_sequence {
!simple : SIMPLE vr_ad_sequence;
body() @driver.clock is only {
do simple keeping {
.reg_kind == EX_REGS_TX_MODE;
System Verification Methodology

Version 2.0 Beta 1

4-29

The Register and Memory Model


Using the Register Features

.direction == WRITE;
.reg_data == 0xaaaa;
};
};
};

4.5.6.2

Accessing Entire Register Files

For accessing all registers in a register file, you must implement a dedicated sequence. For example:
extend EX_FILE_ACCESS vr_ad_sequence {
body() @driver.clock is {
// Get a reference to the register file in the e model
var ex_file = driver.addr_map.get_reg_file_by_kind(EX_FILE)
for each (e_model_reg) in ex_file.get_all_regs() {
do op keeping {
.direction
== WRITE;
.static_item == e_mode_reg;
};
};
};
};

4.6

Using the Register Features

This section contains:

Implementing Side Effects on page 4-31


Reset on page 4-33
Coverage on page 4-33
Backdoor Operations on page 4-36
Indirect Addressing on page 4-40
Changing the Register Field Order on page 4-44
Customizing Addressing Width on page 4-45
Register Sequences and End of Test on page 4-46
Controlling Message Verbosity on page 4-46
Accessing Multiple Address Maps on the Bus on page 4-47
Disabling Comparison for Registers on page 4-48
4-30

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Implementing Side Effects

Register Field Attributes on page 4-49

4.6.1

Implementing Side Effects

A post_access() hook is provided to implement side effects triggered by accessing a register. This hook
is activated only after completion of an update(), fetch(), or compare_and_update() operation;
however, it does provide access to the original value of the register before the operation and to the
parameters of the operation itself.
The post_access() hook method can be used for checking the legality of the register values. For
example, you could verify that a reserved field (resv) of EX_REGS_TX_MODE is always zero as
follows:
extend EX_REGS_TX_MODE vr_ad_reg {
post_access(direction : vr_ad_rw_t) is only {
check that resv == 0 else
dut_error("resv value must be 0 in ", me);
};
};

You can also use the post_access() hook to implement side effects such as clear on read:
extend EX_REGS_TX_MODE vr_ad_reg {
// Clear on Read
post_access(direction : vr_ad_rw_t) is {
if direction == READ {
write_reg_val(0x0);
};
};
};

The pre_access() hook method provides similar capabilities for actions needed just before the register is
accessed.
Table 4-5 describes the information that you can get inside the pre_access() and post_access() methods.

Table 4-5

Available Information in pre_access() and post_access()

Field / Method

Struct

Description

get_access_data() :
list of byte

vr_ad_reg /
vr_ad_reg_file /
vr_ad_map

Data to be updated or compared.

System Verification Methodology

Version 2.0 Beta 1

4-31

The Register and Memory Model


Implementing Side Effects

Table 4-5

Available Information in pre_access() and post_access() (continued)

Field / Method

Struct

Description

get_access_path() : list
of vr_ad_group

vr_ad_reg /
vr_ad_reg_file /
vr_ad_map

Path of the items that were accessed up to the


register. Usually the first item is the register file
that contains the register, and the second item is
the address map that contains the register file.

get_access_kind() :
vr_ad_acess_t

vr_ad_reg /
vr_ad_reg_file /
vr_ad_map

Access kind: UPDATE, FETCH, or


COMPARE.

get_access_offset() :
vr_ad_addr_t

vr_ad_reg /
vr_ad_reg_file /
vr_ad_map

Offset of the current node that is being


accessed. The absolute address of the access is
the sum of all values of get_access_offset() of
the get_access_parents().

get_prev_value() :
vr_ad_data_t

vr_ad_reg

Previous value of the register.

get_cur_value() :
vr_ad_data_t

vr_ad_reg

Current value of the register.

For a full list of the fields of static_info, see vr_ad_reg_static_info on page 4-77.
These values can be used to update the corresponding value in the agent. For example you could update
the value of cur_reg_value in the agent based on the previous value and the value written into
EX_REGS_TX_MODE as follows:
extend EX_REGS_TX_MODE vr_ad_reg {
post_access(direction : vr_ad_rw_t) is only {
if static_info.written_data ==
0x1 and static_info.prev_value == 0x3 {
get_enclosing_unit(vr_abus_agent).cur_reg_value =
static_info.cur_value;
};
};
};

See Also
Fields and Methods of vr_ad_reg on page 4-75
write_reg_val() on page 4-65

4-32

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Reset

4.6.2

Reset

Each register has a reset value specified in the reg_def macro. This value is restored automatically
whenever the reset() method is called for any register. Typically, reset() is called for register files or
address maps. In that case, the appropriate reset value is assigned to each contained register instance. For
example:
extend XCORE vr_ad_reg_file {
post_generate() is also {
reset();
};
};

4.6.3

Coverage

Coverage information is collected on each register access, that is, each time the update(), fetch(), or
compare_and_update() method is called.
The coverage group vr_ad_reg.reg_access is predefined in the package as follows:
cover reg_access is {
item kind using per_instance;
item direction : vr_ad_rw_t = static_info.direction;
cross kind, direction;
};

This section contains:

Coverage of Register Fields on page 4-33


Adding or Modifying Coverage Definitions on page 4-34
Customizing Coverage Sampling on page 4-35

4.6.3.1

Coverage of Register Fields

To collect coverage for a specific register field:

Add the attribute cov at the end of the reg_fld definition.


For example:
//
NAME
FILE
OFFSET
reg_def EX_REGS_RX_MODE XCORE 32'h00000003
reg_fld dest
: uint(bits:2) : RW
reg_fld frame_kind : uint(bits:2) : RW
reg_fld par_err
: uint(bits:1) : RW
System Verification Methodology

Version 2.0 Beta 1

{
: 0 : cov;
: 0 : cov;
: 0 ;
4-33

The Register and Memory Model


Coverage

reg_fld valid_frame : uint(bits:1) : RW : 0 : cov;


reg_fld resv
: uint(bits:2) : RW : 0 ;
};

Coverage information is collected only on the marked fields: dest, frame_kind, and valid_frame. The
following coverage group would be created for the preceding example. Each coverage item name
contains a prefix of the register kind to avoid name conflicts.
extend EX_REGS_RX_MODE vr_ad_reg {
cover reg_access(kind == EX_REGS_RX_MODE) is also {
item ex_regs_rx_mode_dest : uint(bits:2) = dest;
item ex_regs_rx_mode_frame_kind : uint(bits:2) = frame_kind;
item ex_regs_rx_mode_valid_frame : uint(bits:1) = valid_frame;
};
};

See Also
reg_def Macro on page 4-10

4.6.3.2

Adding or Modifying Coverage Definitions

To add cross coverage:

Extend the specific instance of the coverage group.


For example:
extend EX_REGS_RX_MODE vr_ad_reg {
cover reg_access (kind == EX_REGS_RX_MODE) is also {
cross ex_regs_rx_mode_dest,ex_regs_rx_mode_frame_kind;
};
};

Sometimes you might want to ignore some of the predefined coverage values, for example, when a
status register can only be read and should never be written.
To ignore predefined coverage values:

Extend the coverage definition with ignore.


For example:
extend vr_ad_reg {
cover reg_access is also {
item cross__kind__direction using also ignore=
kind == EX_REGS_TX_MODE and direction == READ or

4-34

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Coverage

kind == EX_REGS_RX_MODE and direction == WRITE;


};
};

To add ranges to an existing coverage item definition:

Extend the definition of the coverage item under the appropriate per-instance subgroup with ranges.
For example:
extend VR_AD_TX_DATA vr_ad_reg {
cover reg_access(kind == VR_AD_TX_DATA) is also {
item vr_ad_tx_data_data using also ranges = {
range([0],"0");
range([1..254],"1..254");
range([255],"255");
};
};
};

4.6.3.3

Customizing Coverage Sampling

You might want to disable coverage sampling of a register file or to manually activate coverage
sampling of a specific register.
To disable coverage sampling of a register file:

Constrain the has_coverage field of the register file to be FALSE.


For example:
extend my_agent {
xcore_file : XCORE vr_ad_reg_file;
keep xcore_file.has_coverage == FALSE;
};

To manually activate coverage sampling of a specific register:

Emit the reg_access event of the appropriate register.


For example:
extend my_agent {
on interrupt {
status_reg.interrupt = TRUE;
emit status_reg.reg_access;
};
};
System Verification Methodology

Version 2.0 Beta 1

4-35

The Register and Memory Model


Backdoor Operations

4.6.4

Backdoor Operations

The backdoor feature lets you access DUT registers directly in zero time without resorting to bus
transactions. You can run any register sequence in backdoor mode by simply turning on the backdoor
flag of the sequence. You can also monitor internal changes in the DUT registers by setting a callback on
a register change. Backdoor accesses are done using the HDL path of the registers. Therefore, you must
specify that information for every register to be backdoor accessed.
This section contains:

Setting the HDL Path of a Register on page 4-36


Backdoor Accessing of Registers on page 4-36\
Monitoring Internal Changes on page 4-38
Overriding the Default Backdoor Implementation on page 4-38
Backdoor Accesses and Update of the Address Map on page 4-39
Backdoor-Related Fields and Methods on page 4-39

4.6.4.1

Setting the HDL Path of a Register

Backdoor access is done using the HDL path of the register. Therefore, specifying the HDL path is a
precondition for using this mechanism.
To specify the HDL path of the register:

Use the set_backdoor_path() method.


For example:
reg_def R1 EX_FILE 0 {
reg_fld data : uint(bits:32) : RW : 0;
set_static_info() is {
set_backdoor_path("r1");
};
};

See Also
vr_ad_reg_static_info on page 4-77

4.6.4.2

Backdoor Accessing of Registers

You can run a single operation or an entire sequence in backdoor mode.


4-36

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Backdoor Operations

To run a single operation in backdoor mode:

Turn on the backdoor flag of the operation (vr_ad_operation).


For example:
extend RWR vr_ad_sequence {
!r1 : R1 vr_ad_reg;
body() @driver.clock is {
read_reg {.backdoor == TRUE} r1;
write_reg {.backdoor == TRUE} r1 {.dest == 3};
};
};

You can achieve similar results with the do op syntax as follows:


do op keeping {
.reg is a R1 vr_ad_reg (r1) and ...;
.backdoor == TRUE;
};

To run an entire sequence in backdoor mode:

Turn on the backdoor flag of the sequence (vr_ad_sequence).


For example:
extend RWR vr_ad_sequence {
!r1 : R1 vr_ad_reg;
body() @driver.clock is {
read_reg r1;
write_reg r1 {.dest == 3};
};
};
extend MAIN vr_ad_sequence {
!rwr : RWR vr_ad_sequence;
body() @driver.clock is {
do rwr keeping {
.backdoor == TRUE;
};
};
};

See Also
write_reg and read_reg Macros on page 4-24
Examples in the vr_ad/examples/backdoor directory
System Verification Methodology

Version 2.0 Beta 1

4-37

The Register and Memory Model


Backdoor Operations

4.6.4.3

Monitoring Internal Changes

In many cases DUT registers are changed internally and not as a result of an external register access.
Those changes are invisible to the verification environment. This can create inconsistency between the
vr_ad model and the DUT registers. You can monitor all internal changes of a register by activating the
backdoor automatic update mechanism. This mechanism uses change() @sim to set a callback on
register changes. For every change in the DUT register, the vr_ad_reg.dut_reg_changed event is
emitted, and the vr_ad model is updated.
To monitor internal changes of a register:

Use set_backdoor_auto_update() to activate the automatic update mechanism.


For example:
reg_def R1 EX_FILE 0 {
reg_fld data : uint(bits:32) : RW : 0;
set_static_info() is {
set_backdoor_path("r1");
set_backdoor_auto_update(TRUE);
};
};

4.6.4.4

Overriding the Default Backdoor Implementation

When the RSD executes a backdoor register operation at the lowest level, it calls the following
write_reg_val_backdoor() and read_reg_val_backdoor() hook methods. The default implementation
is as follows:
extend VR_AD_TX_MODE vr_ad_reg {
write_reg_val_backdoor(data : vr_ad_data_t) is only {
'(static_info.backdoor_path)' = data;
};
read_reg_val_backdoor() : vr_ad_data_t is only {
result = '(static_info.backdoor_path)'
};
};

You might require a non-standard implementation, for example, when your register has fields with a
different backdoor_path.
To override the default backdoor implementation:

Extend the write_reg_val_backdoor() and read_reg_val_backdoor() hook methods.

4-38

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Backdoor Operations

See Also
Fields and Methods of vr_ad_reg on page 4-75
vr_ad_reg_static_info on page 4-77

4.6.4.5

Backdoor Accesses and Update of the Address Map

Updating the address map is usually a monitor job, but monitors cannot recognize backdoor activities.
To keep the address map updated, each register backdoor sequence updates also the address map by
default. (Keep in mind that the address map might not be updated if a register was changed internally by
the DUT.) RSD has another flag that controls whether the result of a backdoor read access will be taken
directly from the address map instead of reading it from the DUT. This feature can be useful when you
want to check your register sequences but the DUT is not ready yet.
To change read access results to be taken directly from the address map:

Constrain vr_ad_sequence_driver.bd_read_from_addr_map to be TRUE.


For example:
extend my_env {
rsd : vr_ad_sequence_driver;
keep rsd.bd_read_from_addr_map == TRUE;
};

4.6.4.6

Backdoor-Related Fields and Methods

Table 4-6

Backdoor-Related Fields and Methods

Field / Method

Struct

Description

backdoor : bool

vr_ad_operation

Enables doing an operation in backdoor mode

read_reg_val_backdoor() :
vr_ad_data_t

vr_ad_reg

Called when doing a backdoor read from a


register

set_backdoor_auto_update(
bool)

vr_ad_reg

Activates monitoring of internal HDL changes


of a register

set_backdoor_path(
path: string)

vr_ad_reg

Sets the backdoor path of a register

set_field_backdoor_path(
field_name: string,
path: string)

vr_ad_reg

Sets the backdoor path of a single register field

System Verification Methodology

Version 2.0 Beta 1

4-39

The Register and Memory Model


Indirect Addressing

Table 4-6

Backdoor-Related Fields and Methods (continued)

Field / Method

Struct

Description

write_reg_val_backdoor(
vr_ad_data_t)

vr_ad_reg

Called when doing a backdoor write to a


register

backdoor : bool

vr_ad_sequence

Enables doing an entire sequence in backdoor


mode

4.6.5

Indirect Addressing

Some registers and register files are not mapped in the address map and can only be accessed indirectly.
In other words, reading and writing of unmapped registers is done through mapped registers. For
example, you could read from an unmapped register by writing the address into a mapped address
register and then reading the data from a data register.
Figure 4-2

Indirect Addressing Model

Address Map

Mapped File

Unmapped File
0x0

mapped_file

addr_reg

0x3

data_reg

0x8

0x1
map_addr_reg
0x2
map data_reg
0x3
0x8
0x4
0x5
0x6

If a register file is unmapped and for use with an indirect access:

Do not assign an address to the unmapped register file (in other words, do not use
vr_ad_map.add_with_offset()).

Add the unmapped register file to the addr_map.reg_file_list by calling


vr_ad_map.add_unmapped_item().

4-40

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Indirect Addressing

Support for indirect register accessing requires the following capabilities:

Driving Driving a register indirectly must be translated into a sequence of accesses to the
corresponding address and data registers (see Driving Indirect Registers on page 4-41).

Monitoring Any access to the mapped registers must be recognized by the monitor and passed to
the unmapped register file (see Identifying and Handling Indirect Access on page 4-43).

See Also
vr_ad_map on page 4-82

4.6.5.1

Driving Indirect Registers

Accessing an unmapped register typically requires several accesses to mapped registers. The logic of
which register to access and how, must be encapsulated in a special INDIRECT sequence. This
sequence should be used to perform the indirect access. You can use the write_reg and read_reg macros
to hide the indirection, making accesses to mapped and unmapped registers looks the same. This section
explains how to create an INDIRECT sequence and activate it automatically via the write_reg and
read_reg macros.
The mode field in vr_ad_sequence determines whether the sequence is an INDIRECT sequence or not.
INDIRECT is a subtype of another when determinant. Therefore, to create a user-defined indirect
sequence, you must write:
extend MY_SEQ INDIRECT vr_ad_sequence {...
Table 4-7 describes the fields of the INDIRECT subtype.

Table 4-7

Fields of INDIRECT vr_ad_sequence

Field

Description

direction: vr_ad_rw_t

Direction READ or WRITE

reg: vr_ad_reg

Content of the unmapped register. For WRITE access, it contains the


data for the register access. For READ access, you must update the
register value in the implementation of the sequence body.

Typically, with indirect registers, the offset of the register in the unmapped register file is taken as data
to the mapped address register. Table 4-8 on page 4-42 describes the method used for this purpose.

System Verification Methodology

Version 2.0 Beta 1

4-41

The Register and Memory Model


Indirect Addressing

Table 4-8

Methods for Getting INDIRECT Information

Method

Struct

Description

get_indirect_addr(map :
vr_ad_map)

vr_ad_reg

This method is used to obtain the offset of the register in


the unmapped register file. The map parameter should
be the address map to which the unmapped register file
was added using add_unmapped_item().

To support indirect register accessing:


1.

Create a dedicated INDIRECT sequence that implements the logic required for accessing an
unmapped register file.
For example:
extend vr_ad_sequence_kind : [ACTIVE_XCORE];
extend ACTIVE_XCORE INDIRECT vr_ad_sequence {
!map_addr : VR_AD_MAP_ADDR vr_ad_reg;
!map_data : VR_AD_MAP_DATA vr_ad_reg;
body() @driver.clock is only {
if direction == WRITE {
write_reg map_addr {.addr ==
reg.get_indirect_addr(driver.addr_map)};
write_reg map_data {.data == reg.read_reg_val()};
} else {
write_reg map_addr {.addr ==
reg.get_indirect_addr(driver.addr_map)};
read_reg map_data;
// Important: Update the returned register
reg.write_reg_val(map_data.read_reg_val());
};
};
};

2.

Specify the name of the sequence to be executed when doing an indirect access by calling
vr_ad_reg_file.set_indirect_seq_name().

3.

Add the unmapped register file to the address map using add_unmapped_item() (instead of
add_with_offset()).

For example:
extend ex_c_bus_env {
indirect_reg_file : XCORE vr_ad_reg_file;
post_generate() is also {
indirect_reg_file.set_indirect_seq_name(ACTIVE_XCORE);
4-42

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Indirect Addressing

addr_map.add_unmapped_item(indirect_reg_file);
};
};

See Also
write_reg and read_reg Macros on page 4-24
vr_ad_reg_file on page 4-78

4.6.5.2

Identifying and Handling Indirect Access

To keep an unmapped register file updated, the unmapped register file must be notified when any access
to the corresponding (mapped) data register occurs.
To facilitate automatic update of unmapped registers:
1.

Connect the unmapped register file to the appropriate mapped register using the attach() method
with the unmapped register file as a parameter (mapped_reg.attach(unmapped_reg_file)).
The mapped register adds the register file to an internal list of items to be notified upon access.
For example:
extend ex_c_bus_env {
unmapped_reg_file : XCORE vr_ad_reg_file; // Unmapped reg file
mapped_reg_file : MAP_REGS vr_ad_reg_file; // Mapped reg file
post_generate() is also {
// Add the mapped reg file to the address map
addr_map.add_with_offset(0x0,mapped_reg_file);
// Add the unmapped reg file to the address map
addr_map.add_unmapped_item(unmapped_reg_file);
// Connect the the unmapped reg file to the (mapped) register
// VR_AD_MAP_DATA.
mapped_reg_file.vr_ad_map_data.attach(unmapped_reg_file);
};
};

2.

Implement the indirect_access() method of the unmapped register file to define its behavior upon
notification.
For example:
extend XCORE vr_ad_reg_file {
// References to the mapped registers
!mapped_addr : VR_AD_MAP_ADDR vr_ad_reg;
!mapped_data : VR_AD_MAP_DATA vr_ad_reg;
// On WRITE operation, update the relevant unmapped register.

System Verification Methodology

Version 2.0 Beta 1

4-43

The Register and Memory Model


Changing the Register Field Order

// On READ operation, read from the unmapped register and


// update the (mapped) VR_AD_MAP_DATA register.
indirect_access( direction : vr_ad_rw_t, ad_item : vr_ad_base) is {
if ad_item is a VR_AD_MAP_DATA vr_ad_reg {
if direction == WRITE {
update(mapped_addr.addr,
pack(packing.high,mapped_data.data), {});
} else { // READ
mapped_data.data = fetch(mapped_addr.addr,1)[:];
};
};
};
};
// Initialize the references in the indirect reg file to the mapped
// registers
extend ex_c_bus_env {
post_generate() is also {
unmapped_reg_file.mapped_addr =
mapped_reg_file.vr_ad_map_addr;
unmapped_reg_file.mapped_data =
mapped_reg_file.vr_ad_map_data;
};
};

See Also
Indirect access example in the vr_ad/examples directory

4.6.6

Changing the Register Field Order

The default field order of a register is packing.high, from a high bit position to a low bit position. The
first field declared in the register holds the highest bits and the last field declared in the register holds the
lowest bits. For example, the default field order of the EX_REGS_RX_MODE register is:
//
NAME
FILE
OFFSET
reg_def EX_REGS_RX_MODE XCORE 32'h00000003 {
reg_fld dest
: uint(bits:2);
//
reg_fld frame_kind : uint(bits:2);
//
reg_fld par_err
: uint(bits:1);
//
reg_fld valid_frame : uint(bits:1);
//
reg_fld resv
: uint(bits:2);
//
};

Bits
Bits
Bits
Bits
Bits

[7:6]
[5:4]
[3:3]
[2:2]
[1:0]

Some specs use the opposite field order (packing.low). They interpret the same register definitions as:
//

4-44

NAME

FILE

OFFSET

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Customizing Addressing Width

reg_def EX_REGS_RX_MODE
reg_fld dest
reg_fld frame_kind
reg_fld par_err
reg_fld valid_frame
reg_fld resv
};

XCORE 32'h00000003 {
: uint(bits:2);
//
: uint(bits:2);
//
: uint(bits:1);
//
: uint(bits:1);
//
: uint(bits:2);
//

Bits
Bits
Bits
Bits
Bits

[1:0]
[3:2]
[4:4]
[5:5]
[7:6]

You can change the register packing option for a register file from packing.high to packing.low. The
change affects the packing option for all registers in the file. You cannot change the order for only some
of the registers in a register file.
To change the default packing option of a register file from packing.high to packing.low:

Constrain vr_ad_reg_file.packing_mode to packing.low.


For example:
extend YCORE vr_ad_reg_file {
keep packing_mode == packing.low;
};

See Also
vr_ad_reg_file on page 4-78

4.6.7

Customizing Addressing Width

The default addressing width for a register file is BYTE, which means every address entry contains one
byte only. Typically, memories are presented by address (offset) entries, where each line contains 4 bytes
and the offset jumps by 4 as follows:
byte4

byte3

byte2

byte1

0x0

byte8

byte7

byte6

byte5

0x4

byte12

byte11

byte10

byte9

0x8

Sometimes the required address width is Halfword or Word. In that case, each address entry will contain
two or four bytes instead of one byte as follows:
halfword2

halfword1

0x0

halfword4

halfword3

0x2

System Verification Methodology

Version 2.0 Beta 1

4-45

The Register and Memory Model


Register Sequences and End of Test

halfword6

halfword5

0x4

word1

0x0

word2

0x1

word3

0x2

To define a register file with a different addressing width:

Constrain the field addressing_width_in_bytes of the register file.


For example, you could define a register file with HALFWORD width as follows:
extend vr_ad_reg_file_kind : [MY_HALFWORD_WIDTH];
extend MY_HALFWORD_WIDTH vr_ad_reg_file {
keep addressing_width_in_bytes == 2;
};

4.6.8

Register Sequences and End of Test

Register sequences contain a flag that controls whether the sequence will have an objection to end of test
and will automatically raise and drop an objection to TEST_DONE. By default this flag is turned off. In
other words, by default, register sequences do not influence the end of test decision.
To involve register sequences in the end of test decision:

Constrain vr_ad_sequence.prevent_test_done to TRUE.


extend MAIN vr_ad_sequence {
keep prevent_test_done == TRUE;
};

See Also
Basic Register Operations on page 4-21

4.6.9

Controlling Message Verbosity

By default, the register and memory package prints only messages on activity in the registers. You can
have additional messages relating to the register files and address map by changing the logger verbosity
level to high.
4-46

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Accessing Multiple Address Maps on the Bus

To turn on all messages coming from the register and memory package:

Use the set message command.


For example:
set message @vr_ad_*

Or:

Use the set_actions() method inside your e code.


For example:
sys.logger.set_actions(NONE,{NORMAL},"vr_ad_*","...",add)

To filter out all messages coming from the register and memory package:

Use the set message command with the -remove option.


For example:
set message -remove @vr_ad_*

Or:

Use the set_actions() method inside your e code.


For example:
sys.logger.set_actions(NONE,{NORMAL},"vr_ad_*","...",remove)

The preceding examples assume that the messages are handled by sys.logger. For more information, see
the section on messaging in the e Reuse Methodology (eRM) Developer Manual.

4.6.10

Accessing Multiple Address Maps on the Bus

Some protocols (like the PCI) uses multiple address spaces (MEMORY, IO, CONFIG) on the bus. The
control signals determine which address space to access. The default behavior of vr_ad_sequence_driver
is to work with a single address map specified by a constraint on the addr_map field. Therefore, by
default, sequences can access only registers from one address map.

System Verification Methodology

Version 2.0 Beta 1

4-47

The Register and Memory Model


Disabling Comparison for Registers

To enable access of multiple address maps from a single RSD:


1.

Label each address map with a different enumerated value, and use
vr_ad_sequence_driver.add_space() to add each address map with its label to the RSD map list.
For example:
extend vr_ad_space_kind : [EX_IO, EX_CONFIG1];
extend ex_c_bus_env {
addr_map1 : vr_ad_map;
addr_map2 : vr_ad_map;
rsd
: vr_ad_sequence_driver;
post_generate() is also {
// Two address spaces can be accessed through the bus
rsd.add_space(addr_map1, EX_CONFIG1);
rsd.add_space(addr_map2, EX_IO);
};
};

2.

Use the label in the sequence to specify which address map to access.
For example:
extend MAIN vr_ad_sequence {
!r2 : EX_R2 vr_ad_reg;
// By default, register accesses use the IO space
keep soft addr_space == EX_IO;
body() @driver.clock is only {
...
// Use the CONFIG1 space for this access
write_reg {.addr_space == EX_CONFIG1 } r2 keeping
{.data1 == 3};
};
};

3.

Extend your vr_ad_execute_op() method to check the vr_ad_operation.addr_space field and


translate it to the appropriate transaction.

4.6.11

Disabling Comparison for Registers

In read transactions, the e model compares the data captured from the bus with the information stored in
model. This is done when an eVC monitor calls the compare_and_update() method. Comparison of
registers is done via a comparison mask. By default, the value of the mask is 0xffffffff, meaning compare
all register bits. Change the mask value lets you control which bits to compare.
To disable comparison for a register (or for part of a register):

Call the vr_ad_reg.set_compare_mask() method with the appropriate bits of the parameter set to 0.
4-48

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Register Field Attributes

For example, you could disable comparison of the VR_AD_RX_MODE register as follows:
extend VR_AD_RX_MODE vr_ad_reg {
set_static_info() is {
set_compare_mask(0);
};
};

4.6.12

Register Field Attributes

Table 4-9 describes the register field attributes.

Table 4-9

Attributes of

Attribute

Description

RW

Field is readable and writable

Read Only field. Write access does not change the field

Write Only field. Read access always returns the same value. By
default, the reset value is returned. You can control this with
set_rmask_returned_value()

RC

Read Clear field. Field is cleared after a read access

RW1C

Read Write 1 Clear. Writing 1 clears the corresponding bits in the


register

For example:
reg_def EX_REG {
reg_fld fld1
reg_fld fld2
reg_fld fld3
reg_fld fld4
reg_fld fld5
};

:
:
:
:
:

uint(bits:2):
uint(bits:2):
uint(bits:1):
uint(bits:1):
uint(bits:2):

RW
R
W
RC
RW1C

:
:
:
:
:

0;
0;
0;
0;
0;

Table 4-10 describes the methods you can use to override the field attributes by applying a different
mask value to the register.

System Verification Methodology

Version 2.0 Beta 1

4-49

The Register and Memory Model


Sparse Memory

Table 4-10

Methods that Modify Register Access Attribute

Method

Description

set_wmask(vr_ad_data_t)

Changes the write mask. 0 bits in the mask represent Read Only bits
that do not change by writing to the register

set_rmask(vr_ad_data_t)

Changes the read mask. 0 bits in the mask represent Write Only bits
that can not be read and return always default values no matter what
value is stored in the register

set_rcmask(vr_ad_data_t)

Changes the read-clear mask. 1 bits in the mask clear the


corresponding bits in the register upon reading

set_rw1cmask(vr_ad_data_t)

Changes the rw1c-mask. 1 bits in the mask clear the corresponding


bits in the register upon writing 1 to those bits in the register

For example:
reg_def EX_REG {
set_static_info() is also {
set_wmask(0xff);
set_rmask(0xff00);s
};
};

4.7

Sparse Memory

The vr_ad_mem struct enables modeling of sparse memory. The sparse memory can be used as a
reference model to a real memory located in the DUT or as an external memory implemented solely in e
(for example, the memory of an eVC slave). Memory that is a reference model is instantiated in the
module eVC or in the passive agent corresponding to the DUT. Memory that is an external memory in e
is instantiated in the corresponding active agent.
This section contains:

Instantiating a Memory on page 4-51


Accessing Memory on page 4-51
Updating the Memory on page 4-53
Memory Features on page 4-53
Storing Complex Structures in Memory on page 4-57
Accessing Objects in Memory on page 4-60
4-50

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Instantiating a Memory

4.7.1

Instantiating a Memory

To instantiate a memory:
1.

Extend vr_ad_mem_kind, and add a new kind (according to eRM naming conventions).
For example, you could add the kind EX_MEM as follows:
extend vr_ad_mem_kind : [EX_MEM];

2.

Extend the relevant unit by adding a field of the specific vr_ad_mem subtype, and constrain the
memory to the appropriate size.
For example, you could set a 1Kx64 memory as follows:
extend ACTIVE SLAVE vr_xbus_agent {
mem : EX_MEM vr_ad_mem;
keep mem.size == 0x1024;
keep mem.addressing_width_in_bytes == 8;
};

3.

Add the memory to the address space using add_with_offset() (same as adding a register file)
For example, assuming that the memories of the slaves are mapped in consecutive addresses, you
could map all active XBus slaves as follows:
extend vr_xbus_env {
post_generate() is also {
for each (slave) in active_slaves {
addr_map.add_with_offset(index*1000,slave.mem);
};
};
};

4.7.2

Accessing Memory

As explained in Basic Register Operations on page 21, the same vr_ad_operation is used for register
operations (REG vr_ad_operation) and memory operations (MEM vr_ad_operation). The predefined
field mem_op (of type MEM vr_ad_operation) can be used as a sequence item for doing memory
operations. The memory operations are more general and can also access registers (by specifying a
register address).

System Verification Methodology

Version 2.0 Beta 1

4-51

The Register and Memory Model


Accessing Memory

To access a memory:

Use the predefined field mem_op as a sequence item and constrain its address, data, and direction.
For example:
extend MAIN vr_ad_sequence {
body() @driver.clock is only {
do mem_op keeping {
.direction == WRITE;
.address == 0x10;
.data == {1;2;3;4;5;6;7;8};
};
};
};

Note The above code has an abbreviated form using the write_mem and read_mem macros. See
write_mem and read_mem Macros on page 4-52.

4.7.2.1

write_mem and read_mem Macros

Purpose
Read and write memories.

Syntax
write_mem [{op-block-constraints}] address write-data-exp [mask]
read_mem [{op-block-constraints}] address read-list length
Syntax Example
var data : list of byte;
read_mem 0x100 data 4;
write_mem 0x110 data;

Parameters
op-block-constraints

Block of constraints for generating the operation fields (MEM vr_ad_operation)

address

Address to be accessed

write-data-exp

Data to be written

mask

Mask to apply on the written data

4-52

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Updating the Memory

read_list

List of bytes to be filled by the read operation

length

Number of bytes to read

Example
Writing and reading from a memory.
extend vr_ad_sequence_kind : [EX_SEQ1];
extend EX_SEQ1 vr_ad_sequence {
body() @driver.clock is only {
var rdata : list of byte;
write_mem 0x10 0xaabbccdd; // Write to address 0x10
read_mem 0x10 rdata 4;
// Read 4 bytes from address 0x10
};
};

4.7.3

Updating the Memory

Once you add the memory to the address map and connect the address map to an eVC monitor, the
memory is updated and automatically compares read data.
For example:
extend vr_xbus_bus_monitor_u {
on transfer_end {
if transfer.read_write == WRITE {
env.address_map.update(transfer.addr,%{transfer.data},{});
} else {
compute env.address_map.compare_and_update(
transfer.addr,%{transfer.data});
};
};
};

See Also
Updating the Register Model Using an eVC Monitor on page 4-20.

4.7.4

Memory Features

This section contains:

System Verification Methodology

Version 2.0 Beta 1

4-53

The Register and Memory Model


Memory Features

Reading from and Writing to a File on page 4-54


Controlling Returned Data of Uninitialized Addresses on page 4-54
Side Effects on page 4-55
Memory Backdoor Access on page 4-56

4.7.4.1

Reading from and Writing to a File

You can initialize a memory by reading its content from a file. You can also dump a memory content into
a file. The format of the data file is the format which is supported by verilog.
To initialize the memory from a data file:

Use the method readmemh() (for hex format) or readmemb() (for binary format):
For example:
extend ACTIVE SLAVE vr_xbus_agent {
post_generate() is also {
mem.readmemh("mem_init.txt",
0, MAX_UINT, // Address range of memory to update
0, MAX_UINT); // Address range of file to read
};
};

To dump the memory content into a data file:

Use the method dumpmemh() (for hex format) or dumpmemb() (for binary format):
For example:
extend ACTIVE SLAVE vr_xbus_agent {
finalize() is also {
mem.dumpmemh("mem_data.txt",
0, 0x1000) // Address range of the memory to dump
};
};

4.7.4.2

Controlling Returned Data of Uninitialized Addresses

When the memory is used as an eVC slave memory, you need the ability to control the value of returned
data when reading from uninitialized addresses. By default, reading from an uninitialized address
returns zero. You can change the default behavior to return a random value or a specific value. For more
complex behavior, you can override the memory get_data() method.

4-54

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Memory Features

To return a random value:

Constrain the vr_ad_mem.read_default_value field to RANDOM.


For example:
extend ACTIVE SLAVE vr_xbus_agent {
mem : vr_ad_mem;
keep mem.read_default_value == RANDOM;
};

To define a particular logic for the returned value:

Extend the vr_ad_mem.get_data() method for a specific memory subtype, and implement your own
logic in it.
For example:
extend vr_ad_mem_kind : [EX_MEM];
extend ACTIVE SLAVE vr_xbus_agent {
mem : EX_MEM vr_ad_mem;
};
extend EX_MEM vr_ad_mem {
get_data(addr : vr_ad_addr_t, size : uint) : list of byte is only {
if address < 0x100 {
// Set the size of the list and fill it with 0xbb
result.resize(size,TRUE,0xbb,TRUE);
} else {
// Set the size of the list and fill it with 0xaa
result.resize(size,TRUE,0xaa,TRUE);
};
};
};

4.7.4.3

Side Effects

Like any addressable item, the pre_access() memory method is called before an access to the memory,
and the post_access() memory method is called after an access to the memory. You can use these hooks
to implement side effects.

See Also
Implementing Side Effects on page 4-31

System Verification Methodology

Version 2.0 Beta 1

4-55

The Register and Memory Model


Memory Features

4.7.4.4

Memory Backdoor Access

Memory backdoor access lets you directly access a memory implemented in Verilog or VHDL. Like
register access, you must specify the memory backdoor_path and access is done using the read_mem
and write_mem macros with the backdoor flag turned on.
To set the memory backdoor_path:
1.

Constrain the vr_ad_mem.backdoor_path to the HDL path name.


For example:
extend ACTIVE SLAVE vr_xbus_agent {
mem : EX_MEM vr_ad_mem;
keep mem.size == 0x1024;
keep mem.backdoor_path == "~/top/sram";
};

2.

(For Verilog designs only) Add a verilog variable.


For example:
verilog variable ~/top/sram[99:0][7:0];

To perform a memory backdoor access:

Use the read_mem and write_mem macros with the backdoor flag.
For example:
extend vr_ad_sequence_kind : [EX_SEQ2];
extend EX_SEQ2 vr_ad_sequence {
body() @driver.clock is only {
var rdata: list of byte;
write_mem {.backdoor} 0x10 0xaabbccdd; // Write to address 0x10
read_mem {.backdoor} 0x10 rdata 4;
// Read 4 bytes from
// address 0x10
};
};

See Also
Backdoor Operations on page 4-36
Examples in the vr_ad/examples/memory directory

4-56

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Storing Complex Structures in Memory

4.7.5

Storing Complex Structures in Memory

Sometimes you must store complex structures like packets or descriptors in the memory. You might
want to have both a high level (packet) and a low level (list of byte) representation. The following
capabilities are required:

Generating the object, optionally with constraints


Allocating address space for the object
Update the memory with the object content
Automatic update of the object whenever the memory changes
Release of object address space
This section contains:

Creating Memory Objects on page 4-57


Connecting Memory Objects to the Memory on page 4-58
See Also
Accessing Objects in Memory on page 4-60

4.7.5.1

Creating Memory Objects

Memory objects are created with the mem_obj_def macro.The mem_obj_def macro works almost the
same as the reg_def macro.

Syntax
mem_obj_def obj-name {
mem_fld field-name : field-type [: cov];
};
Syntax Example
mem_obj_def EX_DESC {
mem_fld kind
mem_fld data[16]
};

System Verification Methodology

: uint(bits:2) : cov;
: list of byte : cov;

Version 2.0 Beta 1

4-57

The Register and Memory Model


Storing Complex Structures in Memory

Parameters
obj_name

Memory object name. Must follow eRM naming conventions and use a company
prefix

field-name

Memory object field name

field-type

Memory object field type

cov

(Optional) Add coverage for the field

4.7.5.2

Connecting Memory Objects to the Memory

After defining a memory object type, you can generate its content and connect it to the memory by
calling one of the memory methods described in Table 4-11. This allocates (generates) an address space
from the free memory areas using the default memory set (the mem_set field of vr_ad_mem). The
allocation prevents subsequent allocations from using the same address space.
When an object is connected to the memory:

The memory content can be updated using object methods (see Methods for Accessing Objects in
Memory on page 4-61).

The object will be updated automatically on any change in the corresponding memory area.
Table 4-11

vr_ad_mem Memory Object Allocation Methods

Method

Description

alloc_area(min_addr : vr_ad_addr_t,
max_addr : vr_ad_addr_t) : vr_ad_set

Allocates an address space using the default memory


set

alloc_obj(addr : vr_ad_addr_t,
mem_obj : vr_ad_mem_obj) : bool

Allocates address space for a memory object using the


default memory set

alloc_obj_rnd(min_addr : vr_ad_addr_t,
max_addr : vr_ad_addr_t, mem_obj :
vr_ad_mem_obj, alignment : uint) :
vr_ad_addr_t

Allocates a random address space in


[min_addr..max_addr] range using the default memory
set

alloc_obj_from_set(addr : vr_ad_addr_t,
mem_obj : vr_ad_mem_obj, set :
vr_ad_set) : bool

Allocates address space using the specified set

4-58

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Storing Complex Structures in Memory

Table 4-11

vr_ad_mem Memory Object Allocation Methods (continued)

Method

Description

alloc_obj_rnd_from_set(min_addr :
vr_ad_addr_t, max_addr : vr_ad_addr_t,
mem_obj : vr_ad_mem_obj, set :
vr_ad_set, alignment : uint) :
vr_ad_addr_t

Allocates a random address space in


[min_addr..max_addr] range using the specified set

dealloc_area(min_addr : vr_ad_addr_t,
max_addr : vr_ad_addr_t)

Releases an area to the default memory set

dealloc_obj(mem_obj : vr_ad_mem_obj)

Releases an object to the default memory set

dealloc_obj_to_set(mem_obj :
vr_ad_mem_obj, set : vr_ad_set)

Releases an object to the specified set

get_mem_obj_by_address(addr :
vr_ad_addr_t)

Returns the memory object that is located at the


specified address

Example
You could allocate address space for a list of descriptors as follows:
extend ex_c_bus_env {
mem : vr_ad_mem;
keep mem.mem_size == 1000;
post_generate() is also {
addr_map.add_with_offset(0x100,mem);
};
};
extend MAIN vr_ad_sequence {
descriptors[16] : list of EX_DESC vr_ad_mem_obj;
body() @driver.clock is only {
// Reference to the memory
var mem : vr_ad_mem = driver.addr_map.get_mem_by_address(0x100);
for each (desc) in descriptors {
// Allocate a space from the desriptor
desc_addr = mem.alloc_obj_rnd(0, 1000, desc, 1);
};
};
};

System Verification Methodology

Version 2.0 Beta 1

4-59

The Register and Memory Model


Accessing Objects in Memory

4.7.6

Accessing Objects in Memory

This section contains:

write_mem_obj and read_mem_obj Macros on page 4-60


Methods for Accessing Objects in Memory on page 4-61

4.7.6.1

write_mem_obj and read_mem_obj Macros

Purpose
Read and write objects in memory.

Syntax
write_mem_obj [{op-block-constraints}] object
read_mem_obj [{op-block-constraints}] object

Parameters
op-block-constraints

Block of constraints for generating the operation fields (MEM vr_ad_operation)

object

A memory object instance

Syntax Example
read_mem_obj desc;
write_mem_obj desc;

Example
You could read a descriptor from the memory, modify it, and write it back to the memory as follows:
extend vr_ad_sequence_kind : [EX_SEQ1];
extend EX_SEQ1 vr_ad_sequence {
!cur_desc : EX_DESC vr_ad_mem_obj;
body() @driver.clock is only {
// Reference to the memory
var mem : vr_ad_mem =
driver.addr_map.get_mem_by_address(0x100);
var desc_addr : vr_ad_addr_t;

4-60

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Register and Memory Data Structures

gen cur_desc;
// Allocate random space in range [0..200] with alignment of 4
desc_addr = mem.alloc_obj_rnd(0, 200, cur_desc, 4);
// Read the content of the descriptor from the memory, modify
// it, and write it back to the memory
read_mem_obj cur_desc;
cur_desc.kind = B;
write_mem_obj cur_desc;
};
};

4.7.6.2

Methods for Accessing Objects in Memory

When you change a memory object field, the memory does not update automatically. You must
manually update the memory. You can use the write_mem_obj macro described in write_mem_obj and
read_mem_obj Macros on page 4-60 to update the memory using bus transactions. The backdoor
method for doing this depends on whether the memory is an HDL memory or an e model
Table 4-12 describes the methods that let you access the e model or HDL memory after connecting the

memory object to the memory.


Table 4-12

vr_ad_mem_obj Methods

Method

Description

update_model()

Writes the current content of the object into the e model

write_obj_val_backdoor()

Write the current content of the object into the HDL


memory using backdoor access

read_obj_val_backdoor()

Reads the current content of the object from the memory


using backdoor access

See Also
Examples in the vr_ad/examples/memory directory

4.8

Register and Memory Data Structures

This section contains:

Type Naming Conventions on page 4-62


Type Hierarchy on page 4-62
Register Attribute Structs on page 4-63
System Verification Methodology

Version 2.0 Beta 1

4-61

The Register and Memory Model


Type Naming Conventions

vr_ad_operation on page 4-64


vr_ad_reg on page 4-64
vr_ad_reg_static_info on page 4-77
vr_ad_reg_file on page 4-78
vr_ad_map on page 4-82
vr_ad_mem on page 4-91
vr_ad_sequence_driver on page 4-95

4.8.1

Type Naming Conventions

Table 4-13 shows the type naming conventions used in the register and memory package.

Table 4-13

Register and Memory Package Type Naming Conventions

Type Name

Prefix

Registers and memory

vr_ad

Registers only

vr_ad_reg

Memory only

vr_ad_mem

4.8.2

Type Hierarchy

The addressable items that are implemented in this package are vr_ad_reg, vr_ad_reg_file, and
vr_ad_map. A common base type vr_ad_base provides common interfaces for all of the addressable
items.
Address maps and register files contain a list of addressable items (of type vr_ad_base). Therefore, they
can hierarchically contain other address maps, register files, and registers. The following methods are
common to all addressable items:

update(addr : vr_ad_addr_t, data : list of byte, user_mask : list of byte)


fetch(addr : vr_ad_addr_t, size : vr_ad_addr_t): list of byte
compare_and_update(addr : vr_ad_addr_t, expected_data : list of byte): bool
get_size(): int(bis:*)
reset()

4-62

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Register Attribute Structs

4.8.3

Register Attribute Structs

Register-related attributes are sorted into three structs according to their purpose. This can facilitate
generation of registers on the fly.
For example, an attribute like the write mask is relevant only when you update the e reference model and
should be generated only once, at the beginning of the test. Therefore, it is located in the
vr_ad_reg_static_info struct, which is generated only once.
An attribute like direction (read or write) describes an operation done on a register. It is not an integral
part of a register. Therefore, it is best to locate it in the vr_ad_operation struct.
Table 4-14 describes the structs used to implement the various aspects of registers.

Table 4-14

Register-Related Structs

Struct

Description

vr_ad_operation

Attributes of the operation performed on the register

vr_ad_reg

Physical field of the register

vr_ad_reg_static_info

Attributes that are not generated on the fly

Figure 4-1 shows how the register attributes are divided. (Only the most important fields are listed.)

Figure 4-1

Register Data Structure

Operation (REG
vr_ad_operation):
reg: vr_ad_reg
dest_sd:
any_sequence_driver
direction: vr_ad_rw_t
backdoor_access: bool

Register (vr_ad_reg):
kind: vr_ad_reg_kind
!static_info:
vr_ad_reg_static_info
%field1:
%field2:
...

Static information
(vr_ad_reg_static_info):
offset: vr_ad_addr_t
size: uint
reset_value: vr_ad_data_t
wmask: vr_ad_data_t
compare_mask: bool

See Also
vr_ad_operation on page 4-64
vr_ad_reg on page 4-64
vr_ad_reg_static_info on page 4-77

System Verification Methodology

Version 2.0 Beta 1

4-63

The Register and Memory Model


vr_ad_operation

4.8.4

vr_ad_operation

vr_ad_operation is the data item (sequence item) for register and memory accesses. It encapsulates all
attributes that describe the operation to be done on the register (like direction). For more information,
see Basic Register Operations on page 4-21.

4.8.5

vr_ad_reg

The different register types are modeled using when inheritance. For each register type, a new subtype
of vr_ad_reg_kind is created and the physical fields are added to the specific subtype of vr_ad_reg.
Typically, the definition of a new register is done with the reg_def macro described in Defining
Registers with the reg_def Macro on page 4-9.
Table 4-15

Main Register Operations

Method

Operation

write_reg_val() on page 4-65

Write a value into an e model register, applying the write mask

read_reg_val() on page 4-66

Read a register content

write_reg_raw() on page 4-66

Write a value into the e model register

write_reg_rawval() on page
4-67

Update register content with the specified data

set_static_info() on page 4-68

Set register static information, hook method

set_write_mask() on page 4-69

Set a write mask (mainly for registers with multiple write masks)

set_read_mask() on page 4-70

Set a read mask (mainly for registers with multiple read masks)

set_compare_mask() on page
4-71

Set a compare mask

set_backdoor_path() on page
4-71

Set the backdoor path of a register

set_field_backdoor_path() on
page 4-72

Set the backdoor path for a single register field

update() on page 4-73

Update the e model register

compare_and_update() on
page 4-74

Read from the e model and compare with a given list of byte

4-64

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


vr_ad_reg

Table 4-15

Main Register Operations (continued)

Method

Operation

post_access() on page 4-75

Hook method, called immediately after update(), fetch(), or


compare_and_update()

For a list of all fields and methods of vr_ad_reg, see Fields and Methods of vr_ad_reg on page 4-75.

4.8.5.1

write_reg_val()

Purpose
Update register content.

Syntax
write_reg_val(data : vr_ad_data_t)

Parameters
data

Value to write

Description
The parameter for this method is the vr_ad_data_t type value to be updated (as opposed to a list of bytes
in the update() method). The data in this method is anded with the write mask before it is written to the
register. When using this method, the post_access() hook for side effect is not called, and no coverage is
collected.

Example
extend EX_TX_MODE vr_ad_reg {
post_access(direction : vr_ad_rw_t) is {
write_reg_val(0xffffffff);
};
};

System Verification Methodology

Version 2.0 Beta 1

4-65

The Register and Memory Model


vr_ad_reg

4.8.5.2

read_reg_val()

Purpose
Return the current value of the register.

Syntax
read_reg_val(): vr_ad_data_t

Description
The returned value is of type vr_ad_data_t. When using this method, the post_access() hook for side
effect is not called, and no coverage is collected.

Example
extend ex_c_bus_driver {
reg_seq : REG_SEQ ex_c_bus_sequence;
keep reg_seq.driver == me;
vr_ad_execute_op(op_item : vr_ad_operation) : list of byte
if op_item is a REG vr_ad_operation (reg_op) {
if op_item.direction == WRITE {
reg_seq.write(op_item.address,
reg_op.reg.read_reg_val());
}
};
};
};

4.8.5.3

@clock is {

write_reg_raw()

Purpose
Update register content.

Syntax
write_reg_raw(offset : vr_ad_addr_t, data : vr_ad_data_t, mask : vr_ad_data_t)

4-66

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


vr_ad_reg

Parameters
offset

Bit offset

data

Data to be stored in the register model

mask

Mask to be applied to the operation

Description
The data is shifted with the offset before being written. The method does not consider the static_info
write mask, but it is masked with the mask parameter. If no mask is needed use 0xffffffff (or ~0). When
using this method, the post_access() hook for side effect is not called, and no coverage is collected.

Example
This example shows how to clear register VR_AD_R2 when the clear_r2 field of register VR_AD_R1 is
set to 1.
extend VR_AD_R1 vr_ad_reg {
post_access(direction : vr_ad_rw_t) is {
if clear_r2 == 0x1 {
// Locate target register
var my_reg_file : SIDE_EFFECT_FILE vr_ad_reg_file =
get_parents()[0].as_a(SIDE_EFFECT_FILE vr_ad_reg_file);
// Set the value of the target register
my_reg_file.vr_ad_r2.write_reg_raw(0,0x0,0xffffffff);
};
};
};

4.8.5.4

write_reg_rawval()

Purpose
Update register content with specific data.

Syntax
write_reg_rawval(data : vr_ad_data_t)

System Verification Methodology

Version 2.0 Beta 1

4-67

The Register and Memory Model


vr_ad_reg

Parameters
data

Data to be stored in the register model

Description
This method updates register content with the specified data. It does not consider any mask the data
is written as is.When using this method, the post_access() hook for side effect is not called, and no
coverage is collected.

Example
This example shows how to clear register VR_AD_R2 when the clear_r2 field of register VR_AD_R1 is
set to 1.
extend VR_AD_R1 vr_ad_reg {
post_access(direction : vr_ad_rw_t) is {
if clear_r2 == 0x1 {
// Locate target register
var my_reg_file : SIDE_EFFECT_FILE vr_ad_reg_file =
get_parents()[0].as_a(SIDE_EFFECT_FILE vr_ad_reg_file);
// Set the value of the target register
my_reg_file.vr_ad_r2.write_reg_rawval(0x0);
};
};
};

4.8.5.5

set_static_info()

Syntax
set_static_info()

Description
The reg_def macro sets only the write mask and reset value. Other optional static information like
backdoor path and description must be set by the set_static_info() method.

Example
reg_def R1 {
reg_fld data : uint(bits:32) : RW : 0;

4-68

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


vr_ad_reg

set_static_info() is {
set_backdoor_path("r1");
};
};

4.8.5.6

set_write_mask()

Purpose
Set the write mask of a register.

Syntax
set_write_mask(wmask : vr_ad_data_t, file_or_map : vr_ad_group)

Parameters
wmask

Write mask

file_or_map

Register file or map where the write mask is applied

Description
Sometimes the write-mask value of a register depends on the address space where the register is
accessed. It could be R (read only) when accessing from one address space or RW (read-write) when
accessing from another address space. The set_write_mask() method lets you specify a write-mask
value for a specific address map. If no map is specified, then the write-mask value is fixed and does not
depend on the address map from which it is accessed.

Example
reg_def EX_R1 EX_FILE 0x0 {
reg_fld data2 : uint(bits:8) : RW : 0;
// [23:16]
reg_fld data1 : uint(bits:8) : RW : 0;
// [15: 8]
reg_fld data0 : uint(bits:8) : RW : 0;
// [ 7: 0]
};
extend ex_c_bus_env {
addr_map1 : vr_ad_map;
addr_map2 : vr_ad_map;
ex_file
: EX_FILE vr_ad_reg_file;
post_generate() is also {
// EX_FILE register file is mapped on both address maps with

System Verification Methodology

Version 2.0 Beta 1

4-69

The Register and Memory Model


vr_ad_reg

// different offsets.
addr_map1.add_with_offset(0x00000, ex_file);
addr_map2.add_with_offset(0x01000, ex_file);
// EX_R1 has 2 masks:
// RW - when accessed from addr_map1 (as specified by the macro).
// RO - when accessed from addr_map2.
ex_file.ex_r1.set_write_mask(0x0,addr_map2);
};
};

4.8.5.7

set_read_mask()

Purpose
Set the read mask of a register.

Syntax
set_read_mask(rmask : vr_ad_data_t, file_or_map : vr_ad_group)

Parameters
rmask

Read mask

file_or_map

Register file or map where the read mask is applied

Description
This method sets the registers read mask. If the read-mask value is applicable only when accessing the
register through a specific address map (or register file), you must use the address map (or register file)
for the file_or_map parameter. Otherwise, use NULL.

Example
reg_def EX_R1 EX_FILE 0x0 {
reg_fld data2 : uint(bits:8) : RW : 0;
// [23:16]
reg_fld data1 : uint(bits:8) : RW : 0;
// [15: 8]
reg_fld data0 : uint(bits:8) : RW : 0;
// [ 7: 0]
set_static_info() is also {
set_read_mask(0xff00ff,NULL);
// Note that the above setting is equivalent to writing:
// reg_fld data1 : uint(bits:8) : W : 0;
// in the reg_def macro.
4-70

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


vr_ad_reg

};
};

4.8.5.8

set_compare_mask()

Purpose
Exclude some fields from comparison.

Syntax
set_compare_mask(compare_mask : vr_ad_data_t)

Parameters
compare-mask

Compare mask

Description
This method excludes some fields from comparison.

Example
reg_def R1 {
reg_fld status : uint(bits:32) : R : 0;
set_static_info() is {
set_compare_mask(0);
};
};

4.8.5.9

set_backdoor_path()

Purpose
Set the backdoor path of a register.

Syntax
set_backdoor_path(path : string)

System Verification Methodology

Version 2.0 Beta 1

4-71

The Register and Memory Model


vr_ad_reg

Parameters
path

HDL path of the register for backdoor access

Description
This method sets the backdoor path of a register. The register backdoor mechanism uses this string to
write (write_reg_val_backdoor()) or to read (read_reg_val_backdoor()).

Example
reg_def R1 {
reg_fld status : uint(bits:32) : RW : 0;
set_static_info() is {
set_backdoor_path(r1);
};
};

4.8.5.10 set_field_backdoor_path()
Purpose
Set the backdoor path of a single register field.

Syntax
set_field_backdoor_path(field_name : string, path : string)

Parameters
field_name

Field name

path

HDL path of the field for backdoor access

Description
This method sets the backdoor path of a single register field. It is useful when each register field has a
different HDL path.

4-72

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


vr_ad_reg

Example
reg_def R1 {
reg_fld ctrl1 : uint(bits:8) : RW : 0;
reg_fld ctrl2 : uint(bits:8) : RW : 0;
set_static_info() is {
set_field_backdoor_path("ctrl1","~/top/ctrl1");
set_field_backdoor_path("ctrl2","~/top/ctrl2");
};
};

4.8.5.11 update()
Purpose
Update a specific e model register.

Syntax
update(addr : vr_ad_addr_t, data : list of byte, mask : list of byte)

Parameters
addr

Offset from which to start writing the data.

data

List of byte to write

mask

List of byte to be used as masks. Each element in the list masks the equivalent element
in the data list. 0x0 masks out a byte, and 0xff writes the data as is. An empty list {}
indicates that no masking is applied

Description
This method updates a specific e model register. Usually, you use the address 0, meaning write from the
beginning of the register. You can also use non-zero offsets if the register is in a register file. If you
update a register and you specify a mask, the mask will be anded with the wmask of the register.
Whenever this method is called, the pre_access() and post_access() hooks are activated, and coverage
of the register is collected with direction WRITE.

Example
extend vr_xbus_bus_monitor_u {
on transfer_end {
System Verification Methodology

Version 2.0 Beta 1

4-73

The Register and Memory Model


vr_ad_reg

if transfer.read_write == WRITE {
reg_file.tx_data.update(0,%{transfer.data},{});
};
};
};

4.8.5.12 compare_and_update()
Purpose
Compare a specific register with given data.

Syntax
compare_and_update(addr : vr_ad_addr_t, expected_data : list of byte): bool

Parameters
address

Offset from which to start reading the data

expected_data

List of bytes to be compared to the data stored in the e model

Description
This method compares a specific register with given data. Typically, you use the address 0, meaning
comparing from the beginning of the register. You can also use non-zero offsets if the register is in a
register file. Comparison is done only for the number of bytes given as the expected data. An error is
issued only for a mismatch in a register whose compare_mask bits are set. Whenever this method is
called, the pre_access() and post_access() hooks are activated, and coverage of registers is collected
with direction READ.

Example
extend vr_xbus_bus_monitor_u {
on transfer_end {
if transfer.read_write == READ {
compute p_xbus_env.addr_map.compare_and_update(transfer.addr,
%{transfer.data});
};
};
};

4-74

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


vr_ad_reg

4.8.5.13 post_access()
Purpose
Implement side effects.

Syntax
post_access()

Description
This method is a user hook for implementing features like clear on read and clear on write.

Example
extend EX_REGS_TX_MODE vr_ad_reg {
// Clear on Write
post_access(direction : vr_ad_rw_t) is {
if direction == write{
write_reg_raw(0x0,0x0,0xffffffff);
};
};
};

See Also
Implementing Side Effects on page 4-31

4.8.5.14 Fields and Methods of vr_ad_reg


This section contains:

Table 4-16 on page 4-75


Table 4-17 on page 4-76
Table 4-16

vr_ad_reg Fields

Field

Description

kind: vr_ad_reg_kind

Register kind

System Verification Methodology

Version 2.0 Beta 1

4-75

The Register and Memory Model


vr_ad_reg

Table 4-16

vr_ad_reg Fields

Field

Description

static_info:
vr_ad_reg_static_info

Static information of the register (masks, reset value)

Table 4-17

vr_ad_reg Methods

Method

Description

compare_and_update(addr :
vr_ad_addr_t, data : list of byte): bool

Read from the e model and compare it with a given list of


byte

fetch(addr : vr_ad_addr_t, size : uint):


list of byte

Read from the e model

get_indirect_addr(map : vr_ad_map)

Return the offset of an unmapped register

get_packing_option(): pack_options

Packing option of the register, taken from the register file

get_size(): int(bits: *)

Return the register size in bytes

post_access(direction : vr_ad_rw_t)

Hook method, called immediately after update() and


fetch()

read_reg_rawval(): vr_ad_data_t

Read register content without applying rmask

read_reg_val(): vr_ad_data_t

Read register content (applying rmask)

read_reg_val_backdoor():
vr_ad_data_t:
uint(bits:VR_AD_DATA_WIDTH)

Hook method, backdoor read of HDL register

reset()

Reset the register by restoring its reset value

set_static_info()

User hook to set register static information

set_write_mask(
wmask : vr_ad_data_t,
map : vr_ad_group)

Set a write mask. This method must be used if a single


register has different masks when accessed from different
address spaces. See set_write_mask() on page 4-69

update(addr : vr_ad_addr_t,
data : list of byte,
mask : list of byte)

Update the e model register

4-76

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


vr_ad_reg_static_info

Table 4-17

vr_ad_reg Methods (continued)

Method

Description

write_reg_raw(offset : uint, data :


vr_ad_data_t, mask : vr_ad_data_t)

Write a uint into a register without applying the wmask

write_reg_rawval(data :
vr_ad_data_t)

Write a uint into a register without applying the wmask.


This is a simplified form of write_reg_raw()

write_reg_val(data : vr_ad_data_t)

Write a uint into a register

write_reg_val_backdoor(data :
vr_ad_data_t:
uint(bits:VR_AD_DATA_WIDTH))

Hook method, backdoor write of HDL register

4.8.6

vr_ad_reg_static_info

The vr_ad_reg_static_info struct contains register attributes that should not be generated on the fly when
doing register operations. The static information struct is created only when you add a register to a
register file or to an address map (by add_with_offset()). You can set some fields using
set_static_info() or the reg_def macro. Other fields are automatically updated by the e model.
Table 4-18

vr_ad_reg_static_info Fields

Field

Description

backdoor_path: string

HDL path for backdoor access

compare_mask: vr_ad_data_t

Disables comparison of register data when set to 0. Can be used


to mask all or part of a register

cur_value: vr_ad_data_t

Current value (read-only)

description: string

Description of the register

direction: vr_ad_rw_t

Direction of the register access (READ or WRITE), stored here


for coverage (read-only)

prev_value: vr_ad_data_t

Value before last update (read-only)

reset_value: vr_ad_data_t

Value to be set on reset (set in the reg_def macro)

rmask: vr_ad_data_t

Read mask (updated automatically in the reg_def macro when


W is specified for the field mask)

size: uint

Size of the register in bytes (read-only)

System Verification Methodology

Version 2.0 Beta 1

4-77

The Register and Memory Model


vr_ad_reg_file

Table 4-18

vr_ad_reg_static_info Fields (continued)

Field

Description

wmask: vr_ad_data_t

Write mask (updated automatically in the reg_def macro when


R is specified for the field mask)

written_data: list of byte

Original data before masking (read-only)

4.8.7

vr_ad_reg_file

The register file contains a list of registers (or register files) referenced by vr_ad_node. The
implementation assumes that a register can be accessed through several addresses, and therefore the
address is stored in address nodes rather than the register itself.
Figure 4-1

Register File Nodes

Register File
ad_nodes : list of vr_ad_node
offset 0x0
ad_item

vr_ad_tx_mode
register

offset 0x1
ad_item

vr_ad_tx_data
register

offset 0x2
ad_item

vr_ad_rx_mode
register

offset 0x3
ad_item

vr_ad_rx_data
register

Each vr_ad_node contains an address and a reference to a register, a register file, or a memory block.
Table 4-19

vr_ad_node Fields

Field

Description

ad_item: vr_ad_base

Reference to an addressable item: register, mem, reg_file, or map

offset: vr_ad_addr_t

Offset from the container base address

size: uint

Size of the addressable item

4-78

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


vr_ad_reg_file

All offsets are relative to the base address of the containing object. The absolute address is calculated by
totaling all offsets from the addressable item to the top address map.
Table 4-20

Main Register File Operations

Method

Operation

add_with_offset() on page 4-79

Manually add registers to a register file

For a list of all fields and methods of vr_ad_reg_file, see Fields and Methods of vr_ad_reg_file on page
4-80.

4.8.7.1

add_with_offset()

Purpose
Create an address node with a reference to the register and hold the address of the item.

Syntax
add_with_offset(offset : vr_ad_addr_t, ad_item : vr_ad_base)

Parameters
offset

The desired base address of the addressable item

ad_item

The addressable item to be added to the register file

Description
This method creates an address node with a reference to the register and holds the address of the item.
The parameters for this method are the offset of the register and the register to be added. The reg_def
macro uses this method to automatically add a register to a register file. Explicitly use this method when
a register file contains multiple instances of a register type.

Example
extend XCORE vr_ad_reg_file {
%tx_mode_regs[4] : list of EX_REGS_TX_MODE vr_ad_reg;
post_generate() is also {
for each (reg) in tx_mode_regs {
add_with_offset(index*4,reg);
System Verification Methodology

Version 2.0 Beta 1

4-79

The Register and Memory Model


vr_ad_reg_file

};
};
};

4.8.7.2

Fields and Methods of vr_ad_reg_file

This section contains the following:

Table 4-21 on page 4-80


Table 4-22 on page 4-80
Table 4-21

vr_ad_reg_file Fields

Field

Description

ad_nodes: list (key: offset) of


vr_ad_node

List of all addressable items mapped inside the object

addressing_width_in_bytes

Width of each address entry in bytes. See Customizing


Addressing Width on page 4-45

has_checks

Controls whether to have automatic compare checks.


Default is TRUE

has_coverage

Controls whether to have automatic coverage.


Default is TRUE

indirect_seq_name:
vr_ad_sequence_kind

Name of the sequence to perform for access. Used only


for indirect register files

kind: vr_ad_reg_file_kind

Register file kind

offset: vr_ad_addr_t

Address of the register file

size: vr_ad_addr_t

Number of addresses occupied by the register file. By


default, the size is 0

Table 4-22

vr_ad_reg_file Methods

Method

Description

add_with_offset(offset : vr_ad_addr_t,
ad_item : vr_ad_base)

Adds an addressable item using the specified offset

compare_and_update(addr :
vr_ad_addr_t, data : list of byte): bool

Compares the given data read on the bus with the e model.
Updates the e model if needed

4-80

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


vr_ad_reg_file

Table 4-22

vr_ad_reg_file Methods (continued)

Method

Description

fetch(addr : vr_ad_addr_t, size : uint):


list of byte

Reads from the e model

get_address_by_instance(ad_item :
vr_ad_base): list of vr_ad_addr_t

Returns the addresses of an item; an item may have no


address (not mapped) or several address (mapped in
several addresses)

get_all_nodes(): list of vr_ad_node

Returns the address node list of all addressable items

get_all_nodes_in_range(min_addr :
vr_ad_addr_t, max_addr :
vr_ad_addr_t): list of vr_ad_node

Gets all address nodes in the specified range

get_all_reg_files(): list of
vr_ad_reg_file

Returns all register files, including unmapped register


files

get_all_regs(): list of vr_ad_reg

Returns all registers, including unmapped registers

get_by_address(addr : vr_ad_addr_t):
vr_ad_base

Gets items by address

get_reg_by_address(addr :
vr_ad_addr_t): vr_ad_reg

Gets a register by address

get_reg_by_kind(kind :
vr_ad_reg_kind): vr_ad_reg

Returns the register of the specified kind; if not unique, an


error is issued

get_reg_file_by_address(addr :
vr_ad_addr_t): vr_ad_reg_file

Returns a register file according to the specified address

get_reg_file_by_kind(kind :
vr_ad_reg_file_kind): list of
vr_ad_reg_file

Returns the register file of the specified kind, or error if


there is more than one instance of this kind

get_reg_files_by_kind(kind :
vr_ad_reg_file_kind): list of
vr_ad_reg_file

Returns all the register files of the specified kind

get_regs_by_kind(kind :
vr_ad_reg_kind): list of vr_ad_reg

Returns all registers of the specified kind

is_used(addr : vr_ad_addr_t) : bool

Returns whether the address is occupied by an


addressable item.

System Verification Methodology

Version 2.0 Beta 1

4-81

The Register and Memory Model


vr_ad_map

Table 4-22

vr_ad_reg_file Methods (continued)

Method

Description

read_backdoor(offset : vr_ad_addr_t,
len : uint) : list of byte

Backdoor read from HDL

remove(ad_item : vr_ad_base)

Removes the item

reset()

Reset all registers in the register file

report()

ASCII report of the addressable item

set_indirect_seq_name(kind :
vr_ad_sequence_kind)

Sets the name of the indirect access sequence

update(addr : vr_ad_addr_t, data: list


of byte, mask : list of byte)

Updates the e model

write_backdoor(offset : vr_ad_addr_t,
data : list of byte)

Backdoor write to HDL

4.8.8

vr_ad_map

The address map has all of the functionality of a register file (see vr_ad_reg_file on page 4-78). In
addition, it has address management capabilities (allocation and release of address ranges). The address
management capabilities are discussed in Chapter 4 The Register and Memory Model.
The address map contains a list of register files and memory banks with their absolute addresses. The
address map also manages the unmapped (indirect) register maps, even though they are not mapped in
the address space.
Table 4-23

Main Address Map Operations

Method

Operation

add_with_offset() on page 4-83

Assign an absolute address to an addressable item


(register, register file, or memory bank).

add_to_addr_map() on page 4-84

Assign an address to an addressable item (register, register


file, or memory bank) in a particular address range.

add_unmapped_item() on page 4-85

Register an unmapped register file.

update() on page 4-85

Update the e model.

fetch() on page 4-86

Read a list of bytes from the e model.

4-82

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


vr_ad_map

Table 4-23

Main Address Map Operations (continued)

Method

Operation

compare_and_update() on page 4-87

Read a list of bytes from the e model, and compare it with


an expected list of bytes.

For a full list of all register-related fields and methods of vr_ad_map, see Fields and Methods of
vr_ad_map on page 4-88.

4.8.8.1

add_with_offset()

Purpose
Add an addressable item to the address map at a specific offset.

Syntax
add_with_offset(offset : vr_ad_addr_t, ad_item : vr_ad_base)

Parameters
offset

The desired base address for the addressable item

ad_item

The addressable item to be added to the address map

Description
This method adds an addressable item to the address map at the specified offset. It allocates the required
address space from the free_addrs set and creates an address node with the specified address and a
reference to the addressable item. If the method fails to add the addressable item, an error message is
issued.

Example
extend ex_c_bus_env {
xcore_reg_file : XCORE vr_ad_reg_file;
post_generate() is also {
// Add a reg-file to the address map
addr_map.add_with_offset(0x0,xcore_reg_file);
};

System Verification Methodology

Version 2.0 Beta 1

4-83

The Register and Memory Model


vr_ad_map

};

4.8.8.2

add_to_addr_map()

Purpose
Add an addressable item to the address map.

Syntax
add_to_addr_map(min_addr : vr_ad_addr_t, max_addr : vr_ad_addr_t,
ad_item : vr_ad_base, alignment : uint): vr_ad_addr_t

Parameters
min_addr

Lower bound of the allocated address space

max_addr

Upper bound of the allocated address space

ad_item

Addressable item to be added to the address map

alignment

Alignment of the allocated address space. For example, 2 aligns to halfword and
4 aligns to word

Description
This method adds an addressable item to the address map (similar to add_with_offset()). It lets you
specify the alignment and a range from which to allocate the addresses for the addressable item. The
allocated size will be the size of the addressable item. It creates an address node with the allocated base
address and a reference to the addressable item. The returned value is the allocated base address. If
allocation fails, the returned value is UNDEF.

Example
extend ex_c_bus_env {
xcore_reg_file : XCORE vr_ad_reg_file;
!xcore_base_address : vr_ad_addr_t;
post_generate() is also {
// Add a reg-file to the address map
xcore_base_address=
addr_map.add_to_addr_map(0x0,0x1000,xcore_reg_file,4);
};
};
4-84

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


vr_ad_map

4.8.8.3

add_unmapped_item()

Purpose
Add a register file to the address map.

Syntax
add_unmapped_item(reg_file : vr_ad_reg_file)

Parameters
reg_file

The register file to be added to the address map

Description
This method adds the reg_file and its registers into the reg_list and reg_file_list of the address map lists.
All unmapped register files must be registered in the address map by using this method.

Example
extend ex_c_bus_env {
ycore_reg_file : YCORE vr_ad_reg_file;
post_generate() is also {
// Add the unmapped reg file to the address map
addr_map.add_unmapped_item(ycore_reg_file);
};
};

4.8.8.4

update()

Purpose
Update the e model.

Syntax
update(addr : vr_ad_addr_t, data : list of byte, mask : list of byte)

System Verification Methodology

Version 2.0 Beta 1

4-85

The Register and Memory Model


vr_ad_map

Parameters
addr

Address from which to start writing the data

data

List of byte to write

mask

List of byte to be used as masks. Each element in the list masks the equivalent element
in the data list. 0x0 masks out a byte, and 0xff writes the data as is. An empty list {}
indicates that no masking is applied

Description
This method updates the e model. For example, it can update on the basis of information gathered by the
monitor. If you update a register and you specify a mask, the mask will be anded with the wmask of the
register. Whenever this method is called, the pre_access() and post_access() hooks are activated, and
coverage of registers is collected with direction WRITE.

Example
extend vr_xbus_bus_monitor_u {
on transfer_end {
if transfer.read_write == WRITE {
reg_file.update(transfer.addr,%{transfer.data},
{0x0;0xff;0xff;0xff});
// The update() mask is:
0xffffff00
// Wmask can be, for example:
0x00ffffff
// The actual mask that will be used is: 0x00ffff00
};
};
};

4.8.8.5

fetch()

Purpose
Read a specific number of bytes from the e model starting from a specific address.

Syntax
fetch(addr :vr_ad_addr_t, size : vr_ad_addr_t): list of byte

4-86

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


vr_ad_map

Parameters
addr

Address from which to start reading the data

size

Number of bytes to read

Description
This method reads the specified number of bytes from the e model starting from the specified address.
The address does not have to be aligned to the register boundaries. So, for example, it is legal to start
reading from a second byte of a register. The method recursively calls the fetch methods of the
addressable items inside the address map until it gets to a register that returns its packed value. If there
is a gap between two registers, the gap will be padded with 0s. Whenever this method is called, the
pre_access() and post_access() hooks are activated, and coverage of registers is collected with direction
READ.

Example
extend vr_xbus_bus_monitor_u {
on transfer_end {
if transfer.read_write == READ{
read_data = p_xbus_env.addr_map.fetch(transfer.addr,4);
};
};
};

4.8.8.6

compare_and_update()

Purpose
Compare the data captured on the bus with the data that is stored in the e reference model.

Syntax
compare_and_update(addr : vr_ad_addr_t, expected_data : list of byte): bool

Parameters
address

Address from which to start reading the data

expected_data

List of bytes to be compared to the data stored in the e model

System Verification Methodology

Version 2.0 Beta 1

4-87

The Register and Memory Model


vr_ad_map

Description
This method can be used to automatically compare the data captured on the bus with the data that is
stored in the e reference model. The comparison is done only for the number of bytes given as the
expected data. It does not have to be aligned to the register boundaries. An error is issued only for a
mismatch in a register whose compare_mask bits are set. Whenever this method is called, the
pre_access() and post_access() hooks are activated, and coverage of registers is collected with direction
READ.

Example
extend vr_xbus_bus_monitor_u {
on transfer_end {
if transfer.read_write == READ {
compute p_xbus_env.addr_map.compare_and_update(transfer.addr,
%{transfer.data});
};
};
};

4.8.8.7

Fields and Methods of vr_ad_map

This section contains:

Table 4-24 on page 4-88


Table 4-25 on page 4-89
Table 4-24

vr_ad_map Register-Related Fields

Field

Description

addr_alignment: uint

Default value of alignment for address allocations. For


example, 2 aligns to halfword and 4 aligns to word

free_addrs: vr_ad_set

Address set of free areas

kind: vr_ad_map_kind

Address map kind

occupied_addrs: vr_ad_set

Address set of mapped areas

reg_file_list: list of vr_ad_reg_file

All register files related to the address map

reg_list: list (key: it) of


vr_ad_reg_base

All registers related to the address map

4-88

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


vr_ad_map

Table 4-24

vr_ad_map Register-Related Fields (continued)

Field

Description

size: vr_ad_addr_t

Number of addresses occupied by the address map. By


default, the address map occupies the whole address space.
If the actual size of your address map is smaller, then
constrain this field to the actual size

Table 4-25

vr_ad_map Register-Related Methods

Method

Description

add_to_addr_map(addr : vr_ad_addr_t,
ad_item : vr_ad_base, alignment : uint):
vr_ad_addr_t

Allocates addresses for an addressable item and adds


the item to the address map

add_unmapped_item(reg_file :
vr_ad_reg_file)

Adds an unmapped register file to the address map

add_with_offset(offset : vr_ad_addr_t,
item : vr_ad_base)

Adds an addressable item using the specified offset

compare_and_update(addr :
vr_ad_addr_t, data : list of byte): bool

Compares the given data read on the bus with the e


model. Updates the e model if needed

fetch(addr : vr_ad_addr_t, size : uint): list


of byte

Reads from the e model

get_address_by_instance(ad_item :
vr_ad_base): list of vr_ad_addr_t

Returns the addresses of an item; an item may have


no address (not mapped) or several address (mapped
in several addresses)

get_all_nodes(): list of vr_ad_node

Returns the address node list of all addressable items

get_all_nodes_in_range(min_addr :
vr_ad_addr_t, max_addr : vr_ad_addr_t):
list of vr_ad_node

Gets all addressable items in the specified range

get_all_reg_files(): list of vr_ad_reg_file

Gets all address nodes in the specified range

get_all_regs(): list of vr_ad_reg

Returns all registers, including unmapped registers

get_by_address(addr : vr_ad_addr_t):
vr_ad_base

Gets items by address

System Verification Methodology

Version 2.0 Beta 1

4-89

The Register and Memory Model


vr_ad_map

Table 4-25

vr_ad_map Register-Related Methods (continued)

Method

Description

get_mem_by_address(addr :
vr_ad_addr_t)

Returns the memory instance located at the specified


address

get_reg_by_address(addr : vr_ad_addr_t):
vr_ad_reg

Gets a register by address

get_reg_by_kind(kind : vr_ad_reg_kind):
vr_ad_reg

Returns register of the specified kind, or error if there


is more than one instance of this kind

get_reg_file_by_address(addr :
vr_ad_addr_t): vr_ad_reg_file

Returns a register file according to the specified


address

get_reg_file_by_kind(kind :
vr_ad_reg_file_kind): list of vr_ad_reg_file

Returns the register file of the specified kind, or error


if there is more than one instance of this kind

get_reg_files_by_kind(kind :
vr_ad_reg_file_kind): list of vr_ad_reg_file

Returns all the register files of the specified kind

get_regs_by_kind(kind : vr_ad_reg_kind):
list of vr_ad_reg

Returns all registers of the specified kind

is_valid(addr : vr_ad_addr_t) : bool

Returns whether the address contains valid data

lock_item(item : vr_ad_base): bool

Locks an addressable item, preventing other


sequences from using it

read_backdoor(offset : vr_ad_addr_t, len :


uint) : list of byte

Backdoor read from HDL

release_item(item : vr_ad_base)

Releases an addressable item

remove(ad_item : vr_ad_base)

Removes the item

reset()

Reset all registers in the address map

update(addr : vr_ad_addr_t, data: list of


byte, mask : list of byte)

Updates the e model

write_backdoor(offset : vr_ad_addr_t,
data : list of byte)

Backdoor write to HDL

See Also
Address Management (Sets) on page 4-96
4-90

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


vr_ad_mem

4.8.9

vr_ad_mem

The vr_ad_mem struct provides sparse memory functionality.


Table 4-26

Main Memory Operations

Method

Operation

readmemh() on page 4-91

Loads values from a file into the memory.

dumpmemh() on page 4-92

Dumps the memory content to file.

get_data() on page 4-93

Enables control over returned values of uninitialized addresses.

4.8.9.1

readmemh()

Purpose
Load values into memory.

Syntax
readmemh(file_name : string, start_addr : vr_ad_addr_t, end_addr : vr_ad_addr_t,
file_start_addr : vr_ad_addr_t, file_end_addr : vr_ad_addr_t)

Parameters
file_name

Name of file to read.

start_addr

Data read from file will be written to memory starting from this
address. Typically, the start address is 0.

end_addr

Data read from file will be written up to this address.

file_start_addr

File address to start reading from.

file_end_addr

File address to read up to.

Description
This method loads values from a file into the memory. It is equivalent to the readmemh Verilog task or
VHDL procedure. The format of the file must be according to the standard supported by Verilog or
VHDL. In general, it will have the following structure:

System Verification Methodology

Version 2.0 Beta 1

4-91

The Register and Memory Model


vr_ad_mem

@memory_address data1 data2 data3


The data file might look as follows:
@00 00 01 02 03 04 05 06 07
@08 08 09 0a 0b 0c 0d 0e 0f

Example
extend ex_c_bus_env {
run() is also {
mem.readmemh("data_file.txt",0,1000,0,1000);
};
};

4.8.9.2

dumpmemh()

Purpose
Dump the memory content to file.

Syntax
dumpmemh(file_name : string, start_addr : vr_ad_addr_t, end_addr : vr_ad_addr_t)

Parameters
file_name

Name of file to write.

start_addr

Data will be written to file starting from this memory address.

end_addr

Data will be written to file up to this address.

Description
This method dumps the memory content to file. It is equivalent to the dumpmemh Verilog task or VHDL
procedure. The format of the file must be according to the standard supported by Verilog or VHDL (see
readmemh() on page 4-91).

Example
extend ex_c_bus_env {
finalize() is also {
4-92

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


vr_ad_mem

mem.dumpmemh("data_file.txt",0,100);
};
};

4.8.9.3

get_data()

Purpose
Customize behavior when reading an uninitialized area in the memory.

Syntax
get_data(addr :vr_ad_addr_t, size : vr_ad_addr_t): list of byte

Parameters
addr

Address of the uninitialized area.

size

Number of bytes that should be filled.

Description
This method is called each time an uninitialized area is read in the memory. By default, the returned data
is determined according to the policy in read_default_value. The size of the returned data is according
to the parameter size. If you need a different behavior, you can override this method and implement your
own logic. If you override this method, you must do it only under a specific memory subtype.

Example
extend EX_MEM vr_ad_mem {
get_data(addr : vr_ad_addr_t, size : uint) : list of byte is only {
result.resize(size,TRUE,0,TRUE);
for each (b) in result {
b = addr + index;
};
};
};

The following tables describe the fields and methods of vr_ad_mem.

Table 4-27 on page 4-94


Table 4-28 on page 4-94
System Verification Methodology

Version 2.0 Beta 1

4-93

The Register and Memory Model


vr_ad_mem

Table 4-27

vr_ad_mem Fields

Field

Description

addressing_width_in_bytes: uint

Width of each address entry in bytes. See Customizing


Addressing Width on page 4-45

backdoor_path: string

HDL path for backdoor access

has_checks: bool

Controls whether to have automatic compare checks.


Default is TRUE

kind: vr_ad_mem_kind

Memory kind

read_default_value: [ZERO,
RANDOM]

Controls whether to return 0 (zero) or a generated data when


reading from an uninitialized address

size: vr_ad_addr_t

Number of addresses occupied by the memory. By default,


the size is 0

Table 4-28

vr_ad_mem Methods

Method

Description

get_data(addr : vr_ad_addr_t, size :


uint)

Hook method, called whenever an uninitialized area is read


so that you can provide data

write_backdoor(offset :
vr_ad_addr_t, data : list of byte)

Backdoor write to HDL memory

read_backdoor(offset :
vr_ad_addr_t, len : uint) : list of byte

Backdoor read from HDL memory

dumpmemh(file_name : string,
start_addr : vr_ad_addr_t,
end_addr : vr_ad_addr_t)

Dumps the content of the memory from start_addr to


end_addr using hex formatting

dumpmemb(file_name : string,
start_addr : vr_ad_addr_t,
end_addr : vr_ad_addr_t)

Dumps the content of the memory from start_addr to


end_addr using binary formatting

4-94

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


vr_ad_sequence_driver

Table 4-28

vr_ad_mem Methods (continued)

Method

Description

readmemh(file_name : string,
file_type : string,
start_addr : vr_ad_addr_t,
end_addr : vr_ad_addr_t,
file_start_addr : vr_ad_addr_t,
file_end_addr : vr_ad_addr_t)

Read the content of a hex-format file into the memory

readmemb(file_name : string,
file_type : string,
start_addr : vr_ad_addr_t,
end_addr : vr_ad_addr_t,
file_start_addr : vr_ad_addr_t,
file_end_addr : vr_ad_addr_t)

Read the content of a binary-format file into the memory

4.8.10

vr_ad_sequence_driver

The RSD is a dedicated sequence driver for register and memory operations.

4.8.10.1 Fields and Methods of vr_ad_sequence_driver


This section contains:

Table 4-29 on page 4-95


Table 4-30 on page 4-96
Table 4-29

vr_ad_sequence_driver Fields

Field

Description

addr_map : vr_ad_map

Reference to the address map

default_bfm_sd :
any_sequence_driver

Reference to a sequence driver that will be used for the


register accesses

bd_write_to_addr_map : bool

Controls whether the RSD updates the e model upon


backdoor access

bd_read_from_addr_map : bool

Controls whether RSD reads from the e model on backdoor


access

System Verification Methodology

Version 2.0 Beta 1

4-95

The Register and Memory Model


Address Management (Sets)

Table 4-30

vr_ad_sequence_driver Methods

Method

Description

add_space(space : vr_ad_group,
name : vr_ad_space_kind)

Adds an address space to the RSD. To be used when you


have multiple address spaces (MEMORY, IO, CONFIG) on
the bus

4.9

Address Management (Sets)

The address map (vr_ad_map) provides address management functionality. It lets you define a name
for a group of addresses and then allocate generated addresses from each group of addresses.
For example, assume that you have a slave DUT that responds to several nonconsecutive addresses as
follows [0x0..0x500, 0x2000..0x3000, 0x3500..0x7000].
Figure 4-1

Address Management Model Example


0xffff

slave0_set

0x0
3500..7000

2000..3000

0..500

To randomly access the slave DUT, you would want to generate random areas of various sizes inside the
slave DUT address space. A possible request might be to generate a 50-byte area but not beyond address
0x6000. The address map lets you define a set of slave DUT addresses and then allocate random regions
in it.
To define an address set:
1.

Add a field of type vr_ad_set to your address map.

2.

Use the add_segment() method to initialize the new field with the desired regions.

For example, you could add the field slave0_set to your address map and then initialize it with addresses
[0x0..0x500, 0x2000..0x3000, 0x3500..0x7000] as follows:
extend MY_MAP vr_ad_map {
slave0_set : vr_ad_set;

// Add slave0_set to the address map

post_generate() is also {
// Initialize slave0_set
add_segment(slave0_set,0x0,0x500);
add_segment(slave0_set,0x2000,0x3000);
add_segment(slave0_set,0x3500,0x7000);
};
};
4-96

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Address Management (Sets)

The slave0_set is now initialized with regions: [ 0..0x500, 0x2000..0x3000, 0x3500..0x7000 ]. You can
now allocate random regions from it. Allocation removes the allocated region from the set, making it
unavailable for subsequent allocations. If, for example, you allocated a 40-byte region [0x52..0x91],
then:
slave0_set before allocation: [0
..
0x500, 0x2000..0x3000,
0x3500..0x7000]
slave0_set after allocation : [0..0x51, 0x92..0x500, 0x2000..0x3000,
0x3500..0x7000]

To allocate random regions in an address set:

Use the method alloc_from_set().


For example, you could randomly allocate a region of 10 to 50 bytes inside the address range
[0..0x6000] as follows:
extend MAIN vr_ad_sequence {
body() @driver.clock is only {
// The parameters of alloc_from_set() are:
// The set instance,
// min address, max address (range from where to allocate)
// min size, max size (number of bytes to allocate)
// alignment
var allocated_region : vr_ad_set =
map.alloc_from_set(map.slave0_set,0,0x6000,10,50,2);
var alloc_addr : vr_ad_addr_t =
allocated_regions.get_address();
};
};

To deallocate an allocated region in an address set:

Use the method dealloc_to_set().


For example, you could deallocate the allocated region back to slave0_set as follows:
extend MAIN vr_ad_sequence {
body() @driver.clock is only {
var allocated_set :=
map.alloc_from_set(map.slave0_set,0,0x500,10,50,1);
// ...
// Deallocate the set
map.deallocate_to_set(map.slave0_set, allocated_set);
};
};

System Verification Methodology

Version 2.0 Beta 1

4-97

The Register and Memory Model


add_segment()

Note Address maps use predefined sets to allocate addresses for the addressable items. Each time you
add a register file to an address map (with add_with_offset() or add_to_addr_map()), the address map
allocates a region from the free_addrs set and adds a region to the occupied_addrs set:
extend vr_ad_map {
free_addrs
: vr_ad_set;
occupied_addrs : vr_ad_set;
};
Table 4-31 describes the main address set operations.

Table 4-31

Main Address Set Operations

Method

Operation

add_segment() on page 4-98

Initializes a set and adds the specified region to it

alloc_from_set() on page 4-99

Allocates a region in a set

dealloc_to_set() on page 4-100

Deallocates a set allocated by the method alloc_from_set()

lock_item() on page 4-101

Locks an addressable item

release_item() on page 4-102

Releases an addressable item locked by lock_item()

For a full list of the memory-management methods, see Memory-Management Methods on page 4-102.

4.9.1

add_segment()

Purpose
Initialize a set, and add a specific region to it.

Syntax
add_segment(set: vr_ad_set, min_addr: vr_ad_addr_t, max_addr: vr_ad_addr_t)

Parameters
set

Name of the set that receives the region

min_addr

Lower bound of the region address

max_addr

Upper bound of the region address

4-98

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


alloc_from_set()

Description
This method initializes a set and adds the specified region to it. You can add several segments to a set. If
you add contiguous segments, they are automatically combined into one segment in the set.

Example
extend EX_MAP vr_ad_map {
slave0_set : vr_ad_set;
post_generate() is also {
add_segment(slave0_set,0x0,0x150);
add_segment(slave0_set,0x220,0x350);
};
};

4.9.2

alloc_from_set()

Purpose
Allocate a region in a set.

Syntax
alloc_from_set(set: vr_ad_set, min_addr: vr_ad_addr_t, max_addr: vr_ad_addr_t, min_size:
vr_ad_addr_t, max_size: vr_ad_addr_t, alignment: uint): vr_ad_set

Parameters
set

Set to allocate from

min_addr

Lower bound of the range to allocate from

max_addr

Upper bound of the range to allocate from

min_size

Lower bound of the size of the region

max_size

Upper bound of the size of the region

alignment

Alignment of the allocated region

System Verification Methodology

Version 2.0 Beta 1

4-99

The Register and Memory Model


dealloc_to_set()

Description
This method allocates a region in a set. The allocation is done randomly between the specified range of
min_addr and max_addr. The size of the region is also randomly generated between min_size and
max_size. The returned value is a new set created from the allocated region. You can get the region base
address and size by the methods vr_ad_set.get_address() and vr_ad_set.get_size(). To allocate the
whole address space (the range 0x0 to 0xffffffff, by default definitions), set min_size and max_size to
zero.

Example
extend MAIN vr_ad_sequence {
body() @driver.clock is only {
// Allocate 10 - 50 bytes between addresses 0 - 0x100 using
// alignment 2
var allocated_set : vr_ad_set =
map.alloc_from_set(map.slave0_set,0,0x100,10,50,2);
var allocated_addr : vr_ad_addr_t = allocated_set.get_address();
};
};

4.9.3

dealloc_to_set()

Purpose
Deallocate a set.

Syntax
dealloc_to_set(dest_set: vr_ad_set, alloc_set: vr_ad_set)

Parameters
dest_set

Destination set for the deallocated region

alloc_set

Set to be deallocated

Description
This method deallocates a set that was previously allocated by the method alloc_from_set().

4-100

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


lock_item()

Example
extend MAIN vr_ad_sequence {
body() @driver.clock is only {
var allocated_set :=
map.alloc_from_set(map.slave0_set,0,0x1000,10,50,2);
// Do something
map.deallocate_to_set(map.slave0_set, allocated_set);
};
};

4.9.4

lock_item()

Purpose
Prevent other sequences from accessing an address.

Syntax
lock_item(ad_item: vr_ad_base): bool

Parameters
ad_item

Addressable item (instantiated in the address map) to be locked

Description
When you have a sequence that needs exclusive access to a register or a register file, you do not want
other sequences to interfere as long as the sequence is not finished. The address map contains a
predefined set for that purpose. The method lock_item() removes the relevant addresses from that
predefined set, preventing other sequences from locking the same addresses.

Example
extend MAIN vr_ad_sequence {
body() @driver.clock is only {
var my_reg = driver.addr_map.get_reg_by_address(0x100);
var item_is_locked = lock_item(my_reg);
if item_is_locked {
// Do something
};
};

System Verification Methodology

Version 2.0 Beta 1

4-101

The Register and Memory Model


release_item()

};

4.9.5

release_item()

Purpose
Release a locked address.

Syntax
release_item(ad_item: vr_ad_base)

Parameters
ad_item

Addressable item to be released

Description
This method releases an addressable item that was previously locked by lock_item().

Example
extend MAIN vr_ad_sequence {
body() @driver.clock is only {
var my_reg = driver.addr_map.get_reg_by_address(0x100);
var item_is_locked = lock_item(my_reg);
if item_is_locked {
// Do something
release_item(my_reg);
};
};

4.9.6

Memory-Management Methods

This section contains:

Table 4-32 on page 4-103


Table 4-33 on page 4-103

4-102

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Memory-Management Methods

Table 4-32

vr_ad_map Memory-Management Methods

Method

Description

add_segment(set: vr_ad_set, min_addr: vr_ad_addr_t,


max_addr: vr_ad_addr_t)

Adds address range into a set

add_to_addr_map(addr: vr_ad_addr_t, ad_item:


vr_ad_base, alignment: uint): vr_ad_addr_t

Allocates addresses for an addressable


item and adds the item to the address
map

add_unmapped_item(reg_file: vr_ad_reg_file)

Adds unmapped register file to the


address map

alloc_from_set(set: vr_ad_set, min_addr: vr_ad_addr_t,


max_addr: vr_ad_addr_t, min_size: vr_ad_addr_t,
max_size: vr_ad_addr_t, alignment: uint): vr_ad_set

Allocates addresses from a set

dealloc_addr_to_set(set: vr_ad_set, min_addr:


vr_ad_addr_t, max_addr: vr_ad_addr_t)

Deallocates addresses into a set

dealloc_to_set(set1: vr_ad_set, set2: vr_ad_set)

Deallocates the given set

intersect(set1: vr_ad_set, set2: vr_ad_set): vr_ad_set

Returns the intersection set

is_in_set(set: vr_ad_set, addr: vr_ad_addr_t): bool

Returns whether the address is in the set

lock_item(item: vr_ad_base): bool

Locks an addressable item, preventing


other sequences from using it

release_item(item: vr_ad_base)

Releases an addressable item

set_alloc_mode(set: vr_ad_set, mode: strategy_type)

Can be random, first_fit, or best_fit

subtract(set1: vr_ad_set, set2: vr_ad_set): vr_ad_set

Returns the subtraction set

union(set1: vr_ad_set, set2: vr_ad_set): vr_ad_set

Returns the union set

Table 4-33

vr_ad_set Methods

Method

Description

get_address()

Returns the first address in the set

get_size()

Returns the size of the set

set_policy(policy : vr_ad_set_policy_t)

Sets the allocation policy [RANDOM, BEST_FIT,


FIRST_FIT]

System Verification Methodology

Version 2.0 Beta 1

4-103

The Register and Memory Model


Registers Visualization

Table 4-33

vr_ad_set Methods (continued)

Method

Description

segments_to_list()

Returns a list of paired addresses. Each pair contains


the start address and end address of a segment in the set

To demonstrate how sets are used to manage the address space:

Run the vr_ad_space_management test.


specview p "load vr_ad/examples/vr_ad_space_management;test"

For an example of AHB eVC sequences that use sets, see vr_ad/examples/vr_ad_ahb_sets.e.

4.10 Registers Visualization


The register and memory package provides graphical representations of your address map and register
files.
To access the registers visualization:

At the Specman> prompt in Specview, issue the show map -win command.
Or:

On the User menu of Specview, choose Show Maps.


A VT window showing the All Address Maps page opens. From that page, you can navigate to all other
visualization pages.
This section explains the various address map visualization pages:

All Address Maps Page on page 4-105

Table with all of the address maps

Top-Level Address Map Page on page 4-105 Top-level content of the address map

4-104

Detailed Address Map Page on page 4-106

Table with the full content of the address map

Register Files Page on page 4-107

All register files related to the address map

Address Sets Page on page 4-108

All memory sets related to the address map

Register File Page on page 4-108

Content of the register file in stripes

Stripe Chart Page on page 4-109

Stripe chart of the RSD sequences

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


All Address Maps Page

4.10.1

All Address Maps Page

This page lists all address maps instantiated in the environment.


The table, shown in Figure 4-2, contains four columns:
Index

Serial number

Map

Hyperlink to the data browser

Top-Level

Button that opens the Top-Level Address Map Page on page 4-105

Detailed

Button that opens the Detailed Address Map Page on page 4-106

Figure 4-2

4.10.2

All Maps Page

Top-Level Address Map Page

The top-level address map page lists the highest level of hierarchy of the address map.
The table, shown in Figure 4-3, contains two columns:
Address

Absolute address of the item

Item

Visualization of the item

System Verification Methodology

Version 2.0 Beta 1

4-105

The Register and Memory Model


Detailed Address Map Page

Figure 4-3

4.10.3

Top-Level Address Map Page

Detailed Address Map Page

The address map page displays a table of all addressable items (registers, register files, and memory
banks) of the selected address map.
The table, shown in Figure 4-4, contains five columns:
Index

Serial number

Address

Absolute address of the item

Item

Hyperlink to the item

Value

For registers, contains the value of the register

Stripe Chart

Opens a page with the content of the item shown as a stripe chart.

In case of hierarchical addressable items (for example, a register file containing a register or another
register file), all items are displayed.

4-106

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Register Files Page

Figure 4-4

4.10.4

Address Map Page

Register Files Page

The Register Files page displays a table of all register files related to the address map. This list contains
mapped and unmapped register files. The columns are the same as in the address map page.
Figure 4-5

Register Files Page

System Verification Methodology

Version 2.0 Beta 1

4-107

The Register and Memory Model


Address Sets Page

4.10.5

Address Sets Page

The Address Sets page shows all memory sets instantiated under the address map. The table, shown in
Figure 4-6, contains two columns:
Name

Name of the field of the set instance

Content

List of all segments in the set


(For each segment, the start address and end address are printed)

Figure 4-6

4.10.6

Address Sets Page

Register File Page

The Register File page displays the content of the register file in a stripe chart view.

4-108

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


Stripe Chart Page

Figure 4-7

4.10.7

Register File Page

Stripe Chart Page

The Seq button on the toolbar of address map pages opens a stripe chart window for the corresponding
RSD sequences. The Stripe Chart page shows all register sequences created during the simulation.

System Verification Methodology

Version 2.0 Beta 1

4-109

The Register and Memory Model


Register and Memory Commands

Figure 4-8

Stripe Chart Page

4.11 Register and Memory Commands


The register and memory package supports the following commands:

show map on page 4-111

Displays the address map, register files and registers

trace ad alloc on page 4-111 Initiates tracing of memory allocation operations

4-110

Version 2.0 Beta 1

System Verification Methodology

The Register and Memory Model


show map

4.11.1

show map

Purpose
Produce address map reports.

Syntax
sh[ow] map [map-index] [-win]

Usage
Four variations of the command are provided:
show map

Shows all address maps in the environment.

show map -win

Shows all address maps in the environment in a VT window.

show map map-index

Produces a report for the specified address map. The index is taken
from the show map command.

show map map-index -win

Opens the address map report in a VT window.

4.11.2

trace ad alloc

Purpose
Turn on the trace messages from address allocation and deallocation.

Syntax
trace ad al[loc]

Usage
The following vr_ad_map methods produce trace messages after the trace command is issued:

alloc_from_set()
dealloc_to_set()
dealloc_addr_to_set()

System Verification Methodology

Version 2.0 Beta 1

4-111

The Register and Memory Model


trace ad alloc

4-112

Version 2.0 Beta 1

System Verification Methodology

TLM Verification

This chapter contains:

Overview on page 5-1


TLM System eVC on page 5-2
TLM Mode on page 5-3
Interfacing with SystemC on page 5-6
Configuration for Working with SystemC on page 5-6
Modifying the SystemC Model on page 5-7
Open TLM Verification Issues on page 5-9
The XBus TLM Demo on page 5-16
The XCore TLM Demo on page 5-18

5.1

Overview

There are three modes of connection between Specman Elite and external agents (simulators, SystemC,
and so on).
Table 5-1

Connection Modes between Specman Elite and External Agents

Mode

Description

Cycle accurate

This is the typical mode for working with simulators. In this mode,
Specman Elite monitors and reacts to changes that occur every
clock cycle. This is the most accurate connection mode, but it is
also the most time-consuming connection mode.

System Verification Methodology

Version 2.0 Beta 1

5-1

TLM Verification
TLM System eVC

Table 5-1

Connection Modes between Specman Elite and External Agents (continued)

Mode

Description

Decoupled timing

This connection mode lets you divide the environment into levels
that run according to different clocks. For example, with the
eCelerator, you can accelerate the low level of your environment
and still run high-level sequences.

Transaction-level modeling
(TLM)

This connection mode is mainly for high-level programming


languages, usually modeling SoC. In this mode, Specman Elite can
send and receive whole data items rather than breaking the data
items down by HDL signals and clock cycles.

This document describes an example of verifying a transaction-level model (TLM) implemented in


SystemC, the problems encountered, and some proposed solutions.
The main challenges when verifying a SystemC TLM model are:

Reuse of the eVC at different abstraction levels


Connecting to SystemC
eRM describes how to write reusable eVCs. This chapter shows how to easily extend the eVCs so that
they can be used to verify TLM models.
Once an eVC is built according to eRM, most of its parts are easily reusable over the different running
modes. If, for example, the data check is based on data items collected by the monitor, it does not matter
to the checker how and when the data items are collected. So, to use the eVC with TLM models, you
only need to change the interface to the model injection and collection of data.
This chapter uses as an example the vr_xbus_tlm package, which extends the vr_xbus eRM eVC and
adds TLM mode to it. For the example, the TLM mode is created as a separate package, but it would also
have been valid to add it in the eVC itself (in the e source directory).
Note This chapter does not explain how to model with SystemC. It also does not document the
Specman/SystemC interface. For the full documentation of Specman Elite and the SystemC interface,
refer to the online help.

5.2

TLM System eVC

The only parts of the verification environment that are dependant on the abstraction level are the lower
level BFM and monitor. For interface eVCs (vr_xbus and vr_xserial from the eRM package), these
are the only units that must be modified. For details on how to do that, see TLM Mode on page 5-3.

5-2

Version 2.0 Beta 1

System Verification Methodology

TLM Verification
TLM Mode

For module and system eVCs (XCore, QSoC, XBridge, and RSoC in the sVM package), only a few
changes are required. The system eVC monitor is based on events and data items emitted and collected
by the monitors in the interface eVCs. The system monitor does not care how those data items were
collected. The required changes in the system eVC are:

The configuration file must define the abstraction level for each interface eVC.
extend vr_xbus_env_u {
keep abstraction_level == TRANSFER;
};

Events and checks that depend on internal information must be modified. For example, the XCore
eVC has some events and checks based on an overflow indication from the DUT. The TLM model
of the XCore does not have such indications, so the overflow event is overridden when in TLM mode.

5.3

TLM Mode

Adding TLM functionality requires definition of a new type to control the abstraction level of the device
under test. For example:
type vr_xbus_abstraction_level_t : [SIGNAL, TRANSFER];

Units that must be subtyped on the basis of this type are the BFMs and monitors that get the additional
TLM functionality. Sometimes you also must subtype the env and agent units to propagate the value (for
example, when the agent controls the generation of the BFM and monitor under it).

5.3.1

TLM Wrapper

As each TLM model might supply a different API, it is better not to connect the eVC directly to the
model, but rather to create a wrapper between the BFM/Monitor and the model API. When a model has
a different API, the verification engineer can extend the wrapper and add data conversion.
For example, if the eVC BFM expects to get a response but the model does not implement that, the
wrapper could create a fake response and pass it to the eVC BFM.
For examples of wrapper code, see TLM BFM on page 5-3 and TLM Monitor on page 5-4.

5.3.2

TLM BFM

When verifying a TLM model, the injection mechanism becomes simple. The BFM does not have to
implement the bus protocol. It only has to transport the transfer to the model.
Following are some parts of the vr_xbus_tlm_master_bfm.e file that describe how to write a TLM BFM
and connect it to the SystemC model.

System Verification Methodology

Version 2.0 Beta 1

5-3

TLM Verification
TLM Monitor

A method_type for transporting a transfer is declared.


method_type vr_xbus_transport_transfer(transfer : vr_xbus_trans_s ):
vr_xbus_tlm_response_s @sys.any;

The BFM has an instance of the output port of the transport method.
transport_transfer : out method_port of vr_xbus_transport_transfer is
instance;

The BFM driving TCM is extended so that instead of performing the bus protocol it passes the transfer
to the wrapper.
private drive_transfer(t : MASTER vr_xbus_trans_s) @synch.clock_rise is {
var cur_resp : vr_xbus_tlm_response_s;
//..
cur_resp = transport_transfer_wrapper(t);
//...
};

The wrapper transports the transfer to the model via the output method port.
transport_transfer_wrapper(t : MASTER vr_xbus_trans_s):
vr_xbus_tlm_response_s @synch.clock_rise is {
result = transport_transfer$(t);
return result;
};

The BFM output method port is bound to the SystemC model (bound to external), and its hdl_path is
constrained to the model API method name.
extend TRANSFER MASTER vr_xbus_bfm_u {
connect_ports() is also {
do_bind(transport_transfer, external);
};
};
extend TRANSFER MASTER vr_xbus_bfm_u {
keep transport_transfer.hdl_path() ==
"~/top->Master0.xbus_tlm_master_trans";
};

5.3.3

TLM Monitor

The traffic in the SystemC model is implemented using the methods of the various entities, unlike RTL
models where there are shared signals that can be monitored. For the eVC monitor to know about passed
traffic, it must get the required information from the SystemC model. The eVC bus monitors implement
5-4

Version 2.0 Beta 1

System Verification Methodology

TLM Verification
TLM Monitor

methods that get a new data item, analyze it, do required updates to the env, emit relevant events, and so
on. The monitors have an instance of an input method port for these methods. The SystemC bus must
call these update methods after each transfer for the monitor to work.
The eVC user guide should list the API provided by the monitor so that the verification engineer can
connect the model methods to the appropriate methods and events in the eVC.
With the various Specman-C interface capabilities, other monitoring techniques can be used, based on
the API provided by the SystemC model. For example, the SystemC channel can provide events
indicating activities on the bus.
Following are some parts of the vr_xbus_bus_monitor_tlm.e file that describe how to write a TLM
monitor and connect it to the SystemC model.
A method_type is declared.
method_type vr_xbus_log_new_transfer(transfer : MONITOR vr_xbus_trans_s,
response: vr_xbus_tlm_response);

The eVC monitor has an instance of an input method port of the logging method. This instance is a
wrapper. It gets the new transfer from the SystemC model and passes it to the monitors main logging
method.
log_new_transfer_wrapper : in method_port of vr_xbus_log_new_transfer
is instance;
log_new_transfer_wrapper(new_transfer : MONITOR vr_xbus_trans_s,
new_response: vr_xbus_tlm_response_s) is {
log_new_transfer(new_transfer, new_response);
//...
};

The eVC monitor defines and implements the main logging method.
private log_new_transfer(new_transfer : MONITOR vr_xbus_trans_s,
new_response: vr_xbus_tlm_response_s) is {
transfer = new_transfer;
//...
};

System Verification Methodology

Version 2.0 Beta 1

5-5

TLM Verification
Interfacing with SystemC

The monitor input method port is bound to the SystemC model (bound to external), and its hdl_path is
constrained to the model API method name.
extend TRANSFER vr_xbus_bus_monitor_u {
keep log_new_transfer_wrapper.hdl_path() == "xbus_log_new_transfer";
};
extend TRANSFER vr_xbus_bus_monitor_u {
connect_ports() is also {
do_bind(log_new_transfer_wrapper, external);
};
};

5.4

Interfacing with SystemC

For interfacing with SystemC, each interface eVC must include a convertor file that enables conversion
of data items from e to C and vice versa. An example of such a file is vr_xbus/sysc/conv_transfers.h. For
more information on writing convertors, see vr_sc2e/docs/sc2e_user_spec.pdf under svm_lib.

5.5

Configuration for Working with SystemC

To work with SystemC, you must make some modifications to the default configuration file. Following
are some parts of the vr_xcore/tlm_sve/vr_xcore_sve_config.e file that describe the necessary changes.
Define the simulator as SYSTEMC.
keep agent() == "SYSTEMC";

Define the HDL path to the top module of SystemC.


keep hdl_path() ==

"top->"; // Path to SystemC module

Add required code to the stub file, specman.cpp. It must include the model header file and the
convertors. It must also define a pointer to the top module in SystemC.
keep agent_code() == {"#include 'xcore_top.h'";
"#include 'conv_transfers.h'";
"#include 'conv_frames.h'";
"using namespace xbus;";
"using namespace xserial;";
"using namespace xcore;";
"extern Xcore_Top *top;" };

5-6

Version 2.0 Beta 1

System Verification Methodology

TLM Verification
Modifying the SystemC Model

See Also
vr_xbus_tlm/tlm_sve/vr_xbus_tlm_config.e

5.6

Modifying the SystemC Model

When integrating your SystemC model with your e code, you must make some modifications to the
SystemC code.
For example, these changes were made to the XCore SystemC model:

Changes to sc_main(): the sVM golden eVCs work in master mode. This means that the SystemC
design is fully responsible for time management and for running the simulation. In consequence, the
following changes were made to the SystemC code:

src/snsc_user was added to the SystemC model so that it can call Specman methods.
Before starting the run, sc_main() must activate Specman Elite by calling
specman_init(started_mode).

sc_main() also calls specman_command() both before and after the run to enable issuing of
pre-run commands (for example, to load the test file) and post-run commands (for example, to
perform post-run analysis).

Data injection is now controlled by the eVC BFM. The main SC_THREAD supplied with the
SystemC model is no longer required, and the file that contains the SystemC thread is no longer
included in the verification environment.

Example of modified sc_main.cpp


#include
#include
#include
#include
#include

<iostream>
<string>
"systemc.h"
"xbus_top.h"
"src/snsc_user.h"

using namespace xbus;


xbus_top* top;
int sc_main(int argc, char* argv[])
{
sc_clock clock("XBus_Clock", 1, SC_NS);
// Bus

System Verification Methodology

Version 2.0 Beta 1

5-7

TLM Verification
Modifying the SystemC Model

top = new xbus_top("Top");


top->xbus_top_clock.bind(clock);
specman_init(started_mode);
// Give SN prompt to enable loading the test.
// Issue pre-run commands and the "test" command.
specman_command();
// Start the test
sc_start();
// Give SN prompt to enable issuing post-run commands
// (for example, to perform post-run analysis).
specman_command();
return 0;
}

When running in slave mode, the run is initiated and controlled by Specman Elite. Therefore, sc_main()
must not issue sc_start(). For example:
#include
#include
#include
#include

<iostream>
<string>
"systemc.h"
"xbus_top.h"

#include "src/snsc_user.h"
using namespace xbus;
xbus_top* top;
int sc_main(int argc, char* argv[])
{
// Bus
top = new xbus_top("Top");
// Slave mode - Specman controls the run.
// Run must not be started by SystemC
return 0;
}

5-8

Version 2.0 Beta 1

System Verification Methodology

TLM Verification
Open TLM Verification Issues

5.7

Open TLM Verification Issues

The TLM eVCs are at a beta level of maturity. Some methodology is still under consideration.
This section contains:

TLM BFM Methodology on page 5-9


TLM Monitor Methodology on page 5-10
Multiple Instances of Input Method Ports on page 5-13
Method Port Location on page 5-14
PV Mode Synchronization Issues on page 5-14
Multi-Level Environments on page 5-15

5.7.1

TLM BFM Methodology

The eVC BFM calls the method implemented in the TLM model with the next data to send. Table 5-2
describes the different ways this can be done.
Table 5-2

TLM BFM Methodology

Methodology
eVC BFM waits
for the activity to
end

eVC BFM starts


TLM model and
continues

Implementation

SystemC
value-returning
output method
port

SystemC void
output method
port

SystemC events

System Verification Methodology

Description
The eVC BFM calls the TLM model method and waits
for its returned value. This methodology is
implemented in the sVM eVCs. For example:
cur_resp =
transport_transfer$(cur_transfer);

The eVC BFM calls a void method of the TLM. The


TLM model emits an event when it completes the
requested activity and the BFM can synchronize to that
event to update its data. This methodology is required
when the model supports pipelining. In that case, the
eVC BFM has to inject more than one data item in
parallel and hence cannot wait for the previous transfer
to complete before sending the next one.

Version 2.0 Beta 1

5-9

TLM Verification
TLM Monitor Methodology

5.7.2

TLM Monitor Methodology

In TLM mode, the eVC monitor gets all required information from the TLM model. Table 5-3 describes
the different ways this can be done. In each case, the TLM model must implement some API for the eVC
to use.
Table 5-3

TLM Monitor Methodology

Methodology
TLM model controls
monitoring

Implementation

Specman Elite
input method
port

Description
The TLM model calls a method of the eVC
monitor, passing to it all required data (for
example, the transfer struct after each transfer).
Note If you want to run the TLM model in
standalone mode, you must include a dummy
monitor method to stand in for the eVC method.

eVC controls
monitoring

SystemC output
method port

SystemC
non-blocking
method

Output method
port

SystemC events

The TLM model implements a monitor method.


This method waits for the transaction completion
and then returns the current data. The eVC monitor
calls the monitor method in a while TRUE loop.

The TLM model emits an event when it has new


data. The eVC monitor connects an event port to
the event. When the event is emitted, the eVC
monitor calls the monitor method. The method can
be blocking, as it immediately returns with the new
data.

In the sVM eVCs, monitoring is implemented using input method ports. This is because currently it is
the safest methodology for synchronization. When working in PV mode, you must ensure that events are
handled in the eVC in the same order as they are emitted by the model. If the model supports the output
method port API, you can use the eVC-controlled approach, but make sure that the eVC monitors call
the TLM model in the same order as the events are emitted.
The advantage of letting the eVC control monitoring is that you can easily disable monitoring by
changing the eVC configuration.
Whichever technique is chosen, the eVC manual should document the supplied API so that the
verification engineer can connect the model methods to the appropriate methods and events in the eVC.

5-10

Version 2.0 Beta 1

System Verification Methodology

TLM Verification
TLM Monitor Methodology

Example 1

Input method port

SystemC
The XBus has a monitor that is sensitive to the event transaction_complete. When this event is emitted,
XBus::Monitor() is activated. XBus::Monitor() calls a method implemented in the eVC.
// The constructor of Xbus
XBus(sc_module_name name)
: sc_module(name)
{
SC_THREAD(Monitor);
sensitive << transaction_complete;
}
// The XBus::Monitor() implementation
void XBus::Monitor(){
while(true){
wait(); // for transaction_complete notification
xbus_log_new_transfer(cur_req, cur_rsp);
};
};

eVC code
The eVC monitor has an input method port. It gets called by the wrapper, which has its own
implementation of this method. The wrappers method port HDL path matches the name of the method
called by the model.
// The eVC monitor method
log_new_transfer(transfer : MONITOR vr_xbus_trans_s,
response: vr_xbus_tlm_response) is {
current_transfer = transfer;
current_response = response;
update_transfer();
};
// The wrapper - connecting to Model, bridging from model to monitor
log_transfer_from_model : in method_port of vr_xbus_log_new_transfer
is instance;
log_transfer_to_monitor : out method_port of vr_xbus_log_new_transfer
is instance;
keep soft log_transfer_from_model.hdl_path() == "xbus_log_transfer";
log_transfer_from_model(transfer : MONITOR vr_xbus_trans_s,
response: vr_xbus_tlm_response_s) is {
log_transfer_to_monitor$(transfer, response);

System Verification Methodology

Version 2.0 Beta 1

5-11

TLM Verification
TLM Monitor Methodology

};

Example 2

Non-blocking output method port

SystemC
The SystemC model implements a transaction-completion indicating event and a method that returns the
current transfer and its response.
sc_event transaction_complete; // A master has completed a transaction
void xbus_tlm_mon_trans(xbus_tlm_request& req, xbus_tlm_response& rsp)
{
req = cur_req;
rsp = cur_rsp;
}

eVC
The eVC monitor uses the SystemC event as a sampling event of its main method. Upon event emission,
the eVC monitor calls the SystemC monitor method.
// Define an event and connect to SystemC event
package bus_transfer_end : in event_port is instance;
keep bus_transfer_end.hdl_path() == "transaction_complete";
// Define an output method port and connect to SystemC method
get_info_from_sc_bus : out method_port of xbus_tlm_transaction is instance;
keep get_info_from_sc_bus.hdl_path() == "xbus_tlm_mon_trans";
update_transfer() @bus_transfer_end$ is {
while TRUE {
// Get transfer and response:
get_info_from_sc_bus$(current_transfer, current_response);
//... Update data
};
};

Example 3

Blocking output method port

SystemC code
The SystemC model has a method that waits for the next transaction. It then returns the current
transaction and the response to it.
void xbus_tlm_mon_trans_blocking(xbus_tlm_request& req,
xbus_tlm_response& rsp) {
wait(transaction_complete);

5-12

Version 2.0 Beta 1

System Verification Methodology

TLM Verification
Multiple Instances of Input Method Ports

req = cur_req;
rsp = cur_rsp;
}

eVC code
The eVC calls the systemC monitor in a while TRUE loop.
poll_info_from_sc_bus : out method_port of vr_xbus_poll_info_from_sc
is instance;
keep soft poll_info_from_sc_bus.hdl_path() ==
"xbus_tlm_mon_trans_blocking";
poll_for_transfers() @sys.any is {
while TRUE {
poll_info_from_sc_bus$(current_transfer, current_response);
update_transfer();
};
};

5.7.3

Multiple Instances of Input Method Ports

When using input method ports, the HDL path of the eVC method is the method name used by the
SystemC code. This name is written to the stub header file with the Specman write stub command. If
there are multiple instances of the unit, there will be two methods with same name. That is illegal, and
the stub file will not compile.
In the XSerial eVC, there are two monitors: RX and TX. Both are instances of the same unit
(vr_xserial_monitor_u). The HDL path of the monitors input method must be defined so that there is
no duplication of names.
The solution in the XSerial eVC is adding an ID to each monitor. The integrator must verify that the IDs
of the agents in the SystemC model match the IDs of the eVC monitors.

eVC code
monitor_id : uint;
new_monitor_frame : in method_port of vr_xserial_log_new_frame
is instance;
keep soft new_monitor_frame.hdl_path() ==
append("xserial_log_new_frame", monitor_id);

SystemC code
void XSerialChannel::Monitor(){
System Verification Methodology

Version 2.0 Beta 1

5-13

TLM Verification
Method Port Location

while(true){
wait();
if (id == 0) {
xserial_log_new_frame0(cur_frame);
};
if (id == 1) {
xserial_log_new_frame1(cur_frame);
};
};
};

5.7.4

Method Port Location

Method ports can be instantiated in any of the following locations:

The unit that implements the method (when you have an input method port)
The unit that uses the method (when you have an output method port)
A general unit at a higher level (typically, the env)
A signal map
In the XBus and XSerial eVCs, ports are instantiated in the unit that uses them: the output method port
instantiated in the BFMs and the input method port instantiated in the monitors.
In other packages, the output method ports are instantiated in the env unit.

5.7.5

PV Mode Synchronization Issues

When the TLM model runs in PV mode, pay special attention to synchronization:

Artificial time: If the whole simulation runs in one cycle, all Specman events have the same time
stamp. This causes ordering issues, false DUT errors, and meaningless test information. To avoid
these problems, the TLM BFM has a wait cycle before each transmission to the TLM model. If there
are 10 transfers in the run, the test will last 10 Specman ticks.

Use of events: When more than one event is emitted by the SystemC model, you risk a
synchronization problem among the various eVC monitors. The system eVC monitor uses events
emitted by the interface monitors. Correctness of the checks depends on the system monitor getting
the events in the same order emitted by the TLM SystemC model. But the order is not always
guaranteed. Events defined using event is are handled by the Specman Elite scheduler, and

5-14

Version 2.0 Beta 1

System Verification Methodology

TLM Verification
Multi-Level Environments

their order is not predictable. For example, in the following code, if events frame_started and
frame_ended are emitted at the same time (which can happen in PV mode), the order of the events
if_frame_started and if_frame_ended is not predictable:
event if_frame_started is cycle @interface.frame_started;
event if_frame_ended is cycle @interface.frame_end_ed;

Prefer use of methods over events


Prefer use of on event rather than event is.
Data item buffering: To maintain the correct order, you might need to add buffering between the
model and the eVC monitor. The buffer would verify that the monitor gets the next data item only
after completing analysis of the current item.

5.7.6

Multi-Level Environments

In the sVM examples, the whole environment is either RTL or TLM. When verifying a mixed
environment, some modifications must be made. For example, consider a system with two devices
connected to a bus, with one device implemented in Verilog and the other in SystemC. At what level
should the bus monitor work? How can it serve both agents?
There are several approaches to these questions, depending on the eVC architecture and the complexity
of the protocol.
Note In all of the following cases, coverage collected via the bus monitor represents activity on both
RTL and TLM. To see specific coverage for each agent, look at the coverage collected via the agent
monitor.

5.7.6.1

Multiple Bus Monitors

A simplified solution is to instantiate the bus monitor several times, one for each level. Each agent
would be connected to the appropriate monitor.

5.7.6.2

Independent Agents

This approach requires each agent to be fully independent. Each agent has its own monitor. All agent
monitors monitor the bus. Each monitor is bound to the appropriate device through ports.

5.7.6.3

Bridge

This approach implements a bridge to connect several abstraction levels. The eVC is defined to work at
one level, and any part of the system that is implemented at another level is connected to the eVC with a
bridge.

System Verification Methodology

Version 2.0 Beta 1

5-15

TLM Verification
The XBus TLM Demo

5.8

The XBus TLM Demo

The XBus TLM demo, implemented in vr_xbus_tlm/*, demonstrates a simple XBus TLM test. The
demo can run on NCSC and OSCI simulators. The scenario created by the demo is a sequence of 10
write transfers, each write followed by a read of the same address.
Note As the XBus eVC employs procedural binding, the demo requires Specman Elite 5.0 or higher.
To run the demo:
1.

(Only when working with the OSCI simulator) Define the environment variables: SYSTEMC and
SYSTEMC_LIB_DIR.

2.

Source Specman-home-dir/env.[c]sh.

3.

Invoke the demo script.


% sn_which.sh vr_xbus_tlm/demo.sh [osci|ncsc]

The demo script launches Specman Elite and SystemC, loads the test file
vr_xbus_tlm/tlm_sve/tests/vr_xbus_tlm_test, and issues the test command.
4.

At the Specman prompt, press Enter to start the demo.

XBus TLM Demo Input


The scenario is implemented using the sequence SEQ_WRITES_AND_READS
vr_xbus_master_sequence, which is defined in vr_xbus_tlm_seq_lib.e. The test has one
SEQ_WRITES_AND_READS sequence of length 10, starting at address 0x10.
extend MAIN vr_xbus_master_sequence {
keep sequence.kind == SEQ_WRITES_AND_READS;
keep count == 1
extend SEQ_WRITES_AND_READS vr_xbus_master_sequence {
keep seq_length == 10;
keep start_data == 0x10;
};

XBus TLM Demo Output


Figure 5-1 on page 5-17 shows the output when running the XBus TLM demo.

5-16

Version 2.0 Beta 1

System Verification Methodology

TLM Verification
The XBus TLM Demo

Figure 5-1

XBus TLM Demo Output

System Verification Methodology

Version 2.0 Beta 1

5-17

TLM Verification
The XCore TLM Demo

5.9

The XCore TLM Demo

The XCore TLM demo, implemented in vr_xcore/tlm_sve/*, demonstrates a simple XCore TLM test.
The demo can run on NCSC and OSCI simulators. The scenario created by the demo programs the
XCore, by writing its registers, to transmit 5 frames on the XSerial.
Note As the XCore eVC employs method ports, the demo requires Specman Elite 4.3 or higher.
To run the demo:
1.

(Only when working with the OSCI simulator) Define the environment variables: SYSTEMC and
SYSTEMC_LIB_DIR.

2.

Source Specman-home-dir/env.[c]sh.

3.

Invoke the demo script.


% sn_which.sh vr_xcore/tlm_demo.sh [osci|ncsc]

The demo script launches Specman Elite and SystemC, loads the test file
vr_xcore/tlm_sve/tests/vr_xcore_program_to_tx.e, and issues the test command.
4.

At the Specman prompt, press Enter to start the demo.

XCore TLM Demo Input


The scenario is implemented using the sequence VR_XCORE_XBUS_WRITE vr_ad_sequence, which
is defined in vr_xcore_registers_sequences.e.
extend MAIN vr_ad_sequence {
-- Write 5 frames
keep count == 5;
keep sequence.kind == VR_XCORE_XBUS_WRITE;
keep prevent_test_done == TRUE;
};

XCore TLM Demo Output


Figure 5-2 on page 5-19 shows some of the output when running the XCore TLM demo.

5-18

Version 2.0 Beta 1

System Verification Methodology

TLM Verification
The XCore TLM Demo

Figure 5-2

XCore TLM Demo Output

System Verification Methodology

Version 2.0 Beta 1

5-19

TLM Verification
The XCore TLM Demo

5-20

Version 2.0 Beta 1

System Verification Methodology

Hardware-Software
Co-Verification

Embedded systems contain some software as part of the DUT. This software must be verified with the
hardware to ensure proper interfacing and co-operation of the software with the hardware.
The first and most important task is verifying the low-level software drivers. As these are the software
methods that directly interface with the hardware, their co-operation must be verified thoroughly.
Occasionally additional levels of the software or even full software applications might be co-verified
with the hardware. In all cases, verification is based on a software eVC and the Generic Software
Adaptor (GSA).
The verification of software presents some additional challenges to the already complex task of
functional verification.

Interfacing with the software requires additional infrastructure such as the GSA.
The visibility of software internals is minimal, which makes monitoring difficult. There is no way
to generate events on method calls or value change without modifying the code.

Software requires many simulation cycles, limiting the simulation to a few seconds of real time. To
overcome this limitation, the software is often run on the host or on an instruction set simulator.

The memory associated with the software can be simulated with various memory models, and the
model could change over the life of a project.

Additional complexity results when the software is a multi-tasking application running on top of an
operating system.
The GSA overcomes these difficulties by providing a generic interface between the verification
environment and the software.
This chapter contains:

System Verification Methodology

Version 2.0 Beta 1

6-1

Hardware-Software Co-Verification
Architecture of Software eVCs

Architecture of Software eVCs on page 6-2


Ports for Software eVCs on page 6-3
BFMs for Software eVCs on page 6-4
Sequences for Software eVCs on page 6-4
The Monitor of the Software eVC on page 6-6
This chapter is based on the vr_rsoc example. A smaller example, ex_gsa, is described in the GSA spec,
which also describes the preparation of GSA and its integration into a specific simulation environment.

6.1

Architecture of Software eVCs

A software eVC is a verification component for embedded software. It drives software by invoking
software methods. It monitors software behavior by collecting information on software variables.
The software eVC contains:

A monitor to collect information on software activations and status


A BFM to drive the software
A sequence driver to generate software sequences
These elements are all contained in an env.
Figure 6-1 shows the software eVC connected to the software drivers with a GSA connection. A virtual

sequence driver activates concurrent sequences in the software eVC and other eVCs.

6-2

Version 2.0 Beta 1

System Verification Methodology

Hardware-Software Co-Verification
Ports for Software eVCs

Figure 6-1

6.2

Example Software eVC Architecture

Ports for Software eVCs

Connect to software via ports to the Generic Software Adaptor. Use method ports to activate software
methods. Use simple ports to retrieve the values of software variables.
The ports are defined in the env. The various components of the eVC use a parent pointer to access the
ports in the env.
method_type read_str (xcore: int) : string @sys.any;
extend vr_qsoc_sw_env_u {
// Define e method port and connect it to the "read_str" c routine
read_str: out method_port of read_str is instance;
keep bind(read_str, external);
keep read_str.hdl_path() == "read_str";
// Define simple port and connect it to the "POS_status" c variable
c_status: in simple_port of status_t is instance;
keep bind(c_status, external);
keep c_status.hdl_path() == "POS_status";
};

System Verification Methodology

Version 2.0 Beta 1

6-3

Hardware-Software Co-Verification
BFMs for Software eVCs

6.3

BFMs for Software eVCs

Software sequence items are executed by the BFM in the software eVC. The BFM is typically very
simple. It gets an item and executes it. The BFM itself has no specific knowledge of the software or of
the interface to it.
extend vr_sw_bfm_u {
!driver: sw_sequence_driver;
driver_call() @sys.any is {
var sitem: sw_sequence_item;
while TRUE {
sitem = driver.get_next_item();
sitem.do_me();
emit driver.item_done;
};
}; // driver_call()
run() is also {
start driver_call();
};
};

Using the BFM mechanism lets you add software access just by including another sequence and the
corresponding port in the env.

6.4

Sequences for Software eVCs

For each software interface you must define both a sequence and a sequence item. The sequence is
needed to enable activation from a virtual sequence driver. The sequence item is needed for the various
visualization tools such as stripe charts.
To use sequences for activation of software:
1.

Define the sequence item.


For example:
type sw_sequence_item_kind: [READ_STR];
struct sw_sequence_item like any_sequence_item {
kind: sw_sequence_item_kind;
};

6-4

Version 2.0 Beta 1

System Verification Methodology

Hardware-Software Co-Verification
Sequences for Software eVCs

2.

Define the sequence.


For example:
sequence sw_sequence using item=sw_sequence_item;

3.

Define the item activation to be executed by the BFM.


For example:
extend sw_sequence_item {
do_me() @driver.clock is undefined; -- call the software method
};

4.

Add a parent pointer to the env that contains the method ports.
For example:
extend sw_sequence_driver {
!p_env: vr_qsoc_sw_env_u; -- access to ports in env
event clock is only @sys.any;
};

Activation Example
The sequence item encapsulates the knowledge of how to invoke the software in a method. The BFM is
responsible to activate that method when the item is sent to the BFM.
extend READ_STR sw_sequence_item {
str: string;
core: int;
do_me() @driver.clock is {
-- Activate the software method
me.str = driver.p_env.read_str$(me.core);
};
nice_string(): string is also {
result = "read_str()";
};
};

The software sequence creates a sequence item and propagates the parameters to it.
extend sw_sequence_kind: [READ_STR];
extend READ_STR sw_sequence {
dr_call: READ_STR sw_sequence_item;
str: string;
core: int;
body() @driver.clock is only {

System Verification Methodology

Version 2.0 Beta 1

6-5

Hardware-Software Co-Verification
The Monitor of the Software eVC

do dr_call keeping {.core == core};


str = dr_call.str;
};
nice_string(): string is also {
result = "read_str()";
};
};

6.5

The Monitor of the Software eVC

The monitor collects information on software method calls and software variables.
Typically, information on method calls and their parameters is collected from the sequence driver.
Collecting this kind of information from the software side requires modifications to the software, which
is not recommended.
To collect the value of a software variable, you must access a port. You need a sampling event, because
software cannot initiate events on change of value.
A simple solution is to sample the software variables each time that a software method is activated.
on sw_api_called {
POS_status = p_env.c_status$;
};

Then coverage can be collected as usual:


cover sw_api_called is {
item method_name using text="SW method called";
item POS_status using text="Status of POS application";
};

6-6

Version 2.0 Beta 1

System Verification Methodology

Standardization Using sVM


Compliance Checks

This chapter discusses the requirements for developing a uniform and high-standard eVC. The tables
that follow list the various sVM compliance checks.
In the compliance check tables, the column that reads RQ/RC/ST indicates the nature of the check:

RQ = Required
RC = Recommended
ST = Statistical
The compliance check tables are:

Packaging and Name Space Compliance Checks on page 7-2


Architecture Compliance Checks on page 7-2
Registers and Memory Compliance Checks on page 7-3
Checking Compliance Checks on page 7-4
Coverage Compliance Checks on page 7-4
Sequences Compliance Checks on page 7-5
Hardware-Software Compliance Checks on page 7-5

System Verification Methodology

Version 2.0 Beta 1

7-1

Standardization Using sVM Compliance Checks


Packaging and Name Space Compliance Checks

7.1
Table 7-1

Packaging and Name Space Compliance Checks


Packaging and Name Space Compliance Checks

Index

Check

RQ/RC/
ST

PKCN

The /sve directory includes *_config.e

RQ

PKDM

The module/system eVC has a demo.sh

RQ

PKDO

The module/system eVC directory has a


/docs subdirectory

RQ

PKEX

The module/system eVC directory has an


/examples subdirectory

RQ

PKNM

Each eVC conforms with eRM naming


rules

RQ

PKSV

The module/system eVC has at least one


/*_sve directory

RQ

PKTS

The /sve directory includes a /tests


subdirectory

RQ

PKVM

The /sve directory includes a /vm


subdirectory with at least one *.vsif file

RQ

7.2
Table 7-2

Comments/
Information

See System eVC Packages


on page 3-5

Architecture Compliance Checks


Architecture Compliance Checks
RQ/RC/
ST

Comments/
Information

Each module eVC has an active_passive


when subtype

RQ

See Module eVC Architecture


on page 3-7

ARCP

All SVE and env units extend


connect_pointers()

RQ

ARIN

Each module/system eVC is instantiated


in a system eVC or in the SVE

RQ

Index

Check

ARAP

7-2

Version 2.0 Beta 1

See Integrating eVCs into an


SVE on page 3-15

System Verification Methodology

Standardization Using sVM Compliance Checks


Registers and Memory Compliance Checks

Table 7-2

Architecture Compliance Checks (continued)


RQ/RC/
ST

Comments/
Information

Each module/system eVC has a memory


map

RC

See Module eVC Architecture


on page 3-7

ARMN

Each module/system eVC has a monitor

RQ

See Module eVC Architecture


on page 3-7

ARMS

The SVE contains at least one


module/system eVC

RQ

See Verifying Systems on


page 3-3

ARNM

Agent and env names are assigned on the


level where they are instantiated

RQ

See Extending Subtypes on


page 3-19

ARRF

Each module eVC has one or more


registers or register files

RC

See Module eVC Architecture


on page 3-7

ARSC

Each module/system eVC includes one


or more scoreboards

RC

See Module eVC Architecture


on page 3-7

ARSI

Monitors in the module eVC have no


direct access to signals

RQ

See Connecting the Monitor


with Ports on page 3-10

ARVD

The SVE instantiates at least one VSD

RQ

See Reusing Sequence


Drivers on page 3-21

Index

Check

ARMM

7.3
Table 7-3

Registers and Memory Compliance Checks


Registers and Memory Compliance Checks

Index

Check

RQ/RC/
ST

Comments/
Information

RMAM

The SVE has a common address map

RQ

See Module eVC Architecture


on page 3-7

RMBF

Each RSD is layered on top of a BFM


sequence driver

RQ

RMME

Some memory is instantiated in the


verification environment

RC

System Verification Methodology

Version 2.0 Beta 1

See Integrating the RSD with


the BFM Sequence Driver on
page 4-18

7-3

Standardization Using sVM Compliance Checks


Checking Compliance Checks

Table 7-3

Registers and Memory Compliance Checks (continued)

Index

Check

RQ/RC/
ST

Comments/
Information

RMSD

The SVE instantiates at least one RSD

RQ

See Module eVC Architecture


on page 3-7

7.4
Table 7-4

Checking Compliance Checks


Checking Compliance Checks
RQ/RC/
ST

Comments/
Information

At least one scoreboard is instantiated in


the SVE

RQ

See Checking on page 3-26

CHDF

Each module/system eVC monitor has all


checks implemented under the
has_checks when subtype

RQ

CHST

The monitor has a has_checks when


subtype

RQ

Index

Check

CHCB

7.5
Table 7-5

Coverage Compliance Checks


Coverage Compliance Checks
RQ/RC/
ST

Comments/
Information

Each module/system eVC has all


coverage definitions implemented under
the has_coverage when subtype

RQ

See Coverage on page 3-23

The monitor has a has_coverage when


subtype

RQ

See Reusing Coverage on

Index

Check

CVDF

CVST

7-4

Version 2.0 Beta 1

page 3-24

System Verification Methodology

Standardization Using sVM Compliance Checks


Sequences Compliance Checks

7.6
Table 7-6

Sequences Compliance Checks


Sequences Compliance Checks
RQ/RC/
ST

Comments/
Information

Sequence libraries are in separate files


under /e, /examples/seq_lib, or
/*_sve/seq_lib

RQ

See Sequences: Module to


System on page 3-22

Each module/system eVC must


implement basic READ WRITE
sequences for each interface

RQ

Index

Check

SQLB

SQRW

7.7
Table 7-7

Hardware-Software Compliance Checks


Hardware-Software Compliance Checks
RQ/RC/
ST

Index

Check

HSAR

Each software eVC has a BFM, sequence


driver, and monitor

RC

HSEV

There is at least one software eVC

RC

System Verification Methodology

Version 2.0 Beta 1

Comments/
Information

See Chapter 6
Hardware-Software
Co-Verification

7-5

Standardization Using sVM Compliance Checks


Hardware-Software Compliance Checks

7-6

Version 2.0 Beta 1

System Verification Methodology

Index

about this book 1-1


access
backdoor 4-39
add() 3-26
add_to_addr_map() 4-84
add_unmapped_item() 4-85
add_with_offset() 4-79, 4-83
adding coverage definitions to system eVCs 3-25
address management model 4-96
address management, modeling 4-96
address map 4-82
fields, register-related 4-88
instantiating 4-15
methods, register-related 4-88
multiple on the bus, accessing 4-47
register files, adding 4-15
updating 4-39
Address Map page 4-105, 4-106, 4-107
Address Sets page 4-108
addressing width, customizing 4-45
All Address Maps page 4-105
All Maps page 4-105
architecture
sVM standardization, developer comments
7-2
architecture of software eVCs 6-2
architecture, eRM 4-7

backdoor
access 4-39
defaults, overriding 4-38
operations 4-36
HDL path, setting 4-36
registers, access 4-36, 4-38
bad module 2-11
badly wired module 2-11
BFM 5-3
TLM 5-3
BFM sequence driver
integrating the register sequence driver 4-18
BFMs for software eVCs 6-4
bridge to the system bus 2-8
bugs in new modules 2-10
bugs, SoC, typical 2-10
bus, CPU 2-7
bus, system 2-8

System Verification Methodology

C
checking 2-14, 3-26
scoreboard 3-26
sVM standardization, developer comments
7-4
checkout station 2-3
commands 4-110
compare_and_update() 4-74, 4-87

Version 2.0 Beta 1

Index-1

Index

comparison, disabling for registers 4-48


compilation 4-2
compliance checks
architecture 7-2
checking 7-4
coverage 7-4
hardware-software 7-5
name space 7-2
packaging 7-2
reset 7-3
sequences 7-5
configuration 3-17
Configuration for Working with SystemC 5-6
configuration struct 3-19
configuration with constraints 3-19
connecting eVCs with pointers 3-16
connecting the monitor with pointers 3-9, 3-10
connecting the monitor with ports 3-10, 3-11
connecting the scoreboard 3-26
Connection Modes between Specman Elite and
External Agents 5-1
content of document 2-2
controllers, peripheral 2-8
controlling the other side 2-14
conventions, naming 4-2
types 4-62
coverage 2-15, 3-23, 4-33
definitions, adding 4-34
definitions, modifying 4-34
of fields, defining 4-14
register fields 4-33
sampling, customizing 4-35
sVM standardization, developer comments
7-4
CPU 2-7
removing 2-13
CPU bus 2-7
creating a family of bus sequences emulating the
software 2-13
creating an interpreter for read/write requests
2-19
creating and loading code 2-18
CVL 2-19
Index-2

D
data structure, register 4-63
data structures 4-61
def_reg macro
defining registers with 4-9
defining types 3-20
Detailed Address Map page 4-106
deterministic configuration sequences, creating
4-25
dispatcher 2-14
DMA 2-9
document
content 2-2
example (the RSoC) 2-3
purpose 2-2
document conventions 1-5
driver and hardware verification 2-17
dumpmemh 4-92

E
end of test 4-46
eRM architecture 4-7
eVC standardization 7-1
checking 7-4
coverage 7-4
developer comments
architecture 7-2
name space 7-2
packaging 7-2
reset 7-2
sequences 7-5
reset 7-3
ex_c_bus environment 4-3
example software eVC architecture 6-3
extending subtypes 3-19

F
features, main, package 4-2
fetch() 4-86
fields
coverage, defining 4-14

Version 2.0 Beta 1

System Verification Methodology

Index

order, registers 4-11, 4-44


order, registers, changing 4-44
register
modifying 4-26
vr_ad_map 4-88
vr_ad_node 4-78
vr_ad_operation 4-22
vr_ad_reg 4-75
vr_ad_reg_file 4-80
vr_ad_reg_static_info 4-77
vr_ad_sequence 4-23, 4-39, 4-41
from module-level to system-level 3-1
full hardware 2-20
full RSoC 2-4

interrupt sequence 2-14


introduction 1-1

L
layering, register sequence drivers 4-17

G
generation, stimulus 3-28
get_data 4-93
golden example QSoC_D DUT 3-1

H
hardware-software
sVM standardization, developer comments
7-5
hardware-software co-verification 6-1
has_checks 3-32
has_coverage 3-33
hierarchy, types 4-62
HW, RSoC 2-6

I
indirect registers
access handling 4-43
addressing 4-40
addressing model 4-40
driving 4-41
identifying 4-43
init sequence 2-14
in-method ports, multiple instance 5-13
instances, register, defining 4-11
integrating eVCs into an SVE 3-15
System Verification Methodology

macros
def_reg
defining registers with 4-9
read_reg 4-24, 4-52
reg_def 4-10
reg_list 4-13
write_reg 4-24, 4-52
main features, package 4-2
map, address 4-82
instantiating 4-15
register files, adding 4-15
updating 4-39
match() 3-26
mem_def 4-57
memory 2-7, 4-50
addresses, uninitialized 4-54
backdoor access 4-56
instantiating 4-51
objects 4-57
accessing in memory 4-60
connecting to memory 4-58
creating 4-57
objects, accessing in memory
methods 4-61
reading from file 4-54
returned data of uninitialized addresses,
controlling 4-54
side effects 4-55
sparse memory 4-50
sVM standardization, developer comments
7-3
updating 4-53
writing to file 4-54
memory model 4-1
message verbosity, controlling 4-46

Version 2.0 Beta 1

Index-3

Index

method port location 5-14


method ports 2-18
methodology
TLM BFM 5-9
TLM monitor 5-10
methods
add_to_addr_map() 4-84
add_unmapped_item() 4-85
add_with_offset() 4-79, 4-83
compare_and_update() 4-74, 4-87
fetch() 4-86
post_access() 4-75
read_reg_val() 4-66
set_read_mask() 4-70
set_static_info() 4-68, 4-69, 4-71
update() 4-73, 4-85
vr_ad_map 4-89, 4-94, 4-96, 4-103
vr_ad_reg 4-58, 4-61, 4-76
vr_ad_reg_file 4-80
vr_ad_set 4-103
write_reg_rawval() 4-67
write_reg_val() 4-65
mirroring
register files 4-16
registers 4-13
model, address management 4-96
model, registers
creating 4-7
integrating 4-7, 4-17
modeling address management (sets) 4-96
module and system eVC architecture 3-6
module eVC architecture 3-7
module eVC coverage 3-24
module eVC in passive (normal) mode 3-13
module eVC in stand-in mode 3-14
monitor 5-4
TLM 5-4
monitor of the software eVC 6-6
monitor, updating register model with 4-20

N
names
name space, eVC standardization, developer
Index-4

comments 7-2
naming conventions 4-2
types 4-62
nodes, register files 4-78
not everything is an SoC 2-3

O
order, register fields 4-11, 4-44
order, register fields, changing 4-44
organizing and using sequence libraries 3-23
overview 4-2

P
package, register
main features 4-2
packages
sVM standardization, developer comments
7-2
peripheral controllers 2-8
point of sale 2-3
ports for software eVCs 6-3
ports,in-method, multiple instances 5-13
post_access() 4-75
preface 2-1
problems arising from the interaction of modules
2-11
PROXY 5-3
purpose of document 2-2
PV mode, synchronization issues 5-14

Q
QSoC eVC 3-8
QSoC_D DUT 3-1

R
random registers, accessing 4-28, 4-29
read_mem_obj 4-60
read_reg macro 4-24, 4-52
read_reg_val() 4-66
readmemh 4-91
reference model 3-14

Version 2.0 Beta 1

System Verification Methodology

Index

reg_def macro 4-10


reg_list macro 4-13
Register File page 4-108
register files 4-78
adding to address map 4-15
defining 4-9
entire, accessing 4-30
instantiating 4-15
mirroring 4-16
nodes 4-78
Register Files page 4-107, 4-109
register instances, defining 4-11
register model
creating 4-7
integrating 4-7, 4-17
monitor for updating 4-20
updating, with monitor 4-20
register package
main features 4-2
register sequence driver
instantiating 4-15
integrating with BFM sequence driver 4-18
register type, defining 4-12
registers 4-1
address, defining 4-8
attribute structs 4-63
backdoor access 4-36, 4-38
data structure 4-63
data width, defining 4-8
defining with def_reg macro 4-9
end of test 4-46
eRM architecture, in 4-7
ex_c_bus environment, in 4-3
field attributes 4-49
field order 4-11, 4-44
field order, changing 4-44
fields, backdoor-related 4-39
fields, modifying 4-26
indirect
access handling 4-43
addressing 4-40
addressing model 4-40
driving 4-41
System Verification Methodology

identifying 4-43
internal changes, monitoring 4-38
layering, sequence driver 4-17
methods, backdoor-related 4-39
mirroring 4-13
model, creating 4-7
model, integrating 4-7, 4-17
random, accessing 4-28, 4-29
sequence driver layering 4-17
sequences 4-46
sVM standardization, developer comments
7-3
using 4-21
writing to specific instance of register type
4-27
registers and the magic of memory-mapped IO
2-8
reuse of register sequences 3-22
reusing coverage 3-24
reusing sequence drivers 3-21
reusing sequences 3-21
RSD
fields, register-related 4-95
instantiating 4-15
integrating with BFM SD 4-18
layering 4-17
methods, register-related 4-95
RSoC 2-3
RSoC DUT 3-2
RSoC hardware 2-7
RSoC hardware verification 2-13
RSoC HW 2-6

S
sc_main.cpp 5-7
scalability 3-27
checking 3-32
grouping checks 3-32
preparing for scalability 3-32
tradeoff 3-33
coverage 3-33
grouping coverage 3-33
overhead, minimizing with coverage

Version 2.0 Beta 1

Index-5

Index

API 3-34
tradeoff 3-34
eVC-specific 3-34
context switching, minimizing 3-35
deterministic behavior, implementing
3-35
monitor sharing 3-35
sequence drivers, optimizing 3-35
messages 3-34
stimulus generation 3-28
scoreboard
connecting 3-26
Seamless and such 2-19
sequence driver
BFM, integrating with register sequence
driver 4-18
register
instantiating 4-15
integrating with BFM sequence driver
4-18
sequence libraries 3-28
sequences 3-21
configuration, deterministic, creating 4-25
libraries 3-28
module to system 3-22
register 4-46
sVM standardization, developer comments
7-5
sequences for software eVCs 6-4
Sequences page 4-110
set_compare_mask() 4-48
set_read_mask() 4-70
set_static_info() 4-68, 4-69, 4-71
side effects, implementing 4-31
simulation modes 2-17
SoC 2-2
HW verification 2-10
SoC bugs, typical 2-10
SoC HW verification 2-10
SoC verification
HW 2-10
why it is different 2-1

Index-6

SoCs are similar to the corresponding board-level


systems 2-3
some typical specifications for the various
sub-DUTs 2-5
sparse memory
See memory
stand-in mode 3-12
stimulus generation
tips 3-29
Stripe Chart page 4-109
structs, register attribute 4-63
structure and functionality of system eVCs 3-4
sub-DUTs 2-5
SVE configuration file 3-20
sVM compliance checks 7-1
sVM library 1-3
sVM release library 1-2
sVM terminology 1-4
svm_lib 1-2
system bus 2-8
system eVC architecture 3-8
system eVC monitor 3-8
system eVC monitor example 3-11
system eVC packages 3-5
system eVCs 3-3
SystemC
configuration for working with 5-6
connection modem 5-1
interfacing with 5-6
model, modifying 5-7
overview 5-1
system-level coverage 3-24

T
terminology 1-4
TLM
BFM 5-3
BFM methodology 5-9
monitor 5-4
monitor methodology 5-10
open issues 5-9
overview 5-1
system eVC 5-2

Version 2.0 Beta 1

System Verification Methodology

Index

XBus demo 5-16


XCore demo 5-18
TLM BFM 5-3
TLM mode 5-1, 5-3
BFM 5-3
monitor 5-4
overview 5-1
SystemC 5-1
TLM monitor 5-4
Top-Level Address Map page 4-105
type, register, defining 4-12
types
hierarchy 4-62
naming conventions 4-62
typical SoC bugs 2-10

U
update() 4-73, 4-85
updating, register model with monitor 4-20

V
variations on a theme 2-9
verbosity, message, controlling 4-46
verifying
full RSoC hardware environment 2-12
hardware with the application software 2-19
HW with the SW 2-16
HW with the SW device drivers 2-17
SoC HW 2-11
XCore 2-12
verifying systems 3-3
visual conventions in this manual 1-5
visualization 4-104, 4-105, 4-106, 4-107, 4-108
Address Map page 4-105, 4-106, 4-107
Address Sets page 4-108
All Address Maps page 4-105
All Maps page 4-105
Detailed Address Map page 4-106
Register File page 4-108
Register Files page 4-107, 4-109
Sequences page 4-110
Stripe Chart page 4-109
System Verification Methodology

Top-Level Address Map page 4-105


vr_ad_map 4-82
fields 4-88
fields, register-related 4-88
methods 4-89, 4-94, 4-96
methods 4-103
methods, register-related 4-88
vr_ad_node 4-78
fields 4-78
vr_ad_operation 4-64
fields 4-22
vr_ad_reg 4-64
fields 4-75
methods 4-58, 4-61, 4-76
vr_ad_reg_file 4-78
fields 4-80
methods 4-80
vr_ad_reg_static_info 4-77
fields 4-77
vr_ad_sequence
fields 4-23, 4-39, 4-41
vr_ad_sequence_driver 4-95
fields, register-related 4-95
methods, register-related 4-95
vr_ad_set
methods 4-103

W
width, addressing, customizing 4-45
write_mem_obj 4-60
write_reg macro 4-24, 4-52
write_reg_rawval() 4-67
write_reg_val() 4-65
writing to specific instance of register type 4-27
wrong assumptions about some module 2-11

X
XBus
TLM demo 5-16
XCore
TLM demo 5-18
XCore DUT 3-6

Version 2.0 Beta 1

Index-7

Index

XCore eVC 3-7


XCore eVC unit verification 2-12

Index-8

Version 2.0 Beta 1

System Verification Methodology

Вам также может понравиться