You are on page 1of 326

e Reuse Methodology

(eRM) Developer
Manual
Version 4.3.4
Legal Notice
Copyright © 2002-2004 Verisity Design, Inc. All rights reserved.

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 Verisity’s 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 reader’s responsibility to determine the applicable
regulations and to comply with them.
Contents

1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1-1
1.1 About This Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-1
1.2 About the eRM Release Library (erm_lib) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-2
1.3 About eVCs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-3
1.3.1 What Are eVCs? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-3
1.3.2 eVCs vs. Regular Verification Environments (VEs) . . . . . . . . . . . . . . . . . . . . 1-4
1.3.3 eVCs as Plug-and-Play Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-5
1.3.4 eVC Reuse Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-5
1.4 Conventions in This Manual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-6

2 Verification Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-1


2.1 What Is a Verification Component Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-1
2.1.1 Packages as e Concept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-2
2.1.2 Kinds of Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-2
2.2 Package-Related Naming Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-3
2.2.1 Choosing a Package Name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-3
2.2.2 evc_util Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-4
2.3 Directory Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-5
2.3.1 Library Directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-7
2.3.2 Package Directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-7
2.3.2.1 PACKAGE_README.txt File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-7
2.3.2.2 demo.sh File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-8
2.3.2.3 e Directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-8
2.3.2.4 Docs Directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-8
2.3.2.5 Examples Directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-8
2.3.2.6 evc_ve Directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-9

e Reuse Methodology iii


Contents

2.3.2.7 Other Directories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-10


2.4 Accessing Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-10
2.4.1 Using Package-Relative File Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-10
2.4.2 Package Shadowing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-11
2.4.3 Importing Files within the Same e Source Directory . . . . . . . . . . . . . . . . . . . 2-11
2.4.4 sn_which.sh Shell Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-11
2.5 Handling Package Versions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-12
2.5.1 Where the Version Number Appears . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-12
2.5.2 Shipping New Versions of a Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-13
2.5.2.1 Simple Method to Pack the Version . . . . . . . . . . . . . . . . . . . . . . . . 2-14
2.5.2.2 Robust Method to Pack the Version . . . . . . . . . . . . . . . . . . . . . . . . 2-14
2.5.3 Declaring Dependencies on Specman Version and Other Packages . . . . . . . 2-15
2.5.3.1 Version Numbers and Ranges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-16
2.5.4 Using the Package Compatibility Analyzer . . . . . . . . . . . . . . . . . . . . . . . . . . 2-16
2.5.4.1 How the Package Compatibility Analyzer Works . . . . . . . . . . . . . . 2-17
2.6 PACKAGE_README.txt File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-19
2.6.1 PACKAGE_README.txt Location . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-19
2.6.2 PACKAGE_README.txt Headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-19
2.7 Checking Package Legality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-22
2.8 any_env Unit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-23
2.8.1 any_env Unit Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-23
2.8.2 User-Visible Methods in any_env . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-24
2.9 show packages Command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-26
2.9.1 Example of show packages Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-26
2.10 Recommend nations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-28
2.10.1 Shipping and Receiving Whole Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-28
2.10.2 Instantiating Non-Env Utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-29
2.10.3 Adding Suffixes to Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-29
2.10.4 Connecting any_env to Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-29

3 eVC File Organization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3-1


3.1 eVC Directory Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-1
3.1.1 evc/e/ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2
3.1.2 evc/examples/ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-3
3.1.3 evc/docs/ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-3
3.2 Partitioning eVC Source into Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-3

iv e Reuse Methodology
Contents

3.3 File Naming Guidelines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-4


3.4 Instantiating Entities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-5
3.5 Importing Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-7
3.6 File Clusters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-7
3.7 Files: Cyclic Dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-8
3.7.1 An Alternative Approach to Cyclic Dependencies . . . . . . . . . . . . . . . . . . . . . 3-9

4 Typical eVC Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4-1


4.1 Basic eVC Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-1
4.1.1 DUT and eVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-2
4.1.1.1 Diagram Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-4
4.1.2 BFMs and Monitors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-5
4.1.3 Clocks and Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-6
4.1.4 DUT Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-6
4.2 A Look at Agents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-6
4.2.1 What Are Agents? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-7
4.2.2 Components of Agents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-8
4.2.2.1 Agent Configuration and Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-9
4.2.2.2 Sequence Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-9
4.2.2.3 Monitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-10
4.2.2.4 BFM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-10
4.2.2.5 Checker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-11
4.2.2.6 Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-11
4.2.3 Some Important Guidelines for Agents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-12
4.3 A More Complex eVC Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-12
4.4 Combining eVCs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-14
4.5 Layering eVCs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-15
4.5.1 Typical Layering Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-15
4.5.2 Requirements for Lower-Layer eVCs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-16
4.5.3 Requirements for Higher-Layer eVCs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-17
4.5.4 Inter-Layer Connection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-18
4.5.4.1 Step 1: Pointers to the Upper Layer . . . . . . . . . . . . . . . . . . . . . . . . . 4-18
4.5.4.2 Step 2: Rx Monitor’s Scoreboard Hook . . . . . . . . . . . . . . . . . . . . . 4-19
4.5.4.3 Step 3: Connector Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-19
4.5.5 Partitioning of Layers and Connections Between Packages . . . . . . . . . . . . . 4-21
4.5.6 Separation of Control in Multi-Layer Sequences . . . . . . . . . . . . . . . . . . . . . . 4-21
4.6 Modeling FAQs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-22

e Reuse Methodology v
Contents

4.7 Terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-23


4.7.1 Main Entities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-23
4.7.2 Sub-Entities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-24
4.7.3 Agent Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-25
4.7.4 Data Item Naming Convention . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-25
4.7.5 Full Legend for Architecture Diagrams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-26

5 Sequences: Constructing Test Scenarios . . . . . . . . . . . . . . . . . . . .5-1


5.1 Introduction to Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-2
5.2 How to Use Sequences in Your Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-4
5.3 Getting Started with Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-5
5.3.1 Defining the Sequence Item . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-5
5.3.2 Defining the Sequence and Its Driver Using the sequence Statement . . . . . . . 5-5
5.3.2.1 Sequence Struct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-7
5.3.2.2 Sequence Driver Unit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-7
5.3.2.3 Item Struct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-8
5.3.2.4 Sequence Kind Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-8
5.3.3 Hooking the Sequence Driver to the Environment . . . . . . . . . . . . . . . . . . . . . 5-9
5.4 Implementing Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-11
5.4.1 Implementing a Scenario Using the Sequence Struct . . . . . . . . . . . . . . . . . . 5-12
5.4.1.1 Defining the Behavior of Sequences . . . . . . . . . . . . . . . . . . . . . . . . 5-12
5.4.1.2 Activating Items and Subsequences . . . . . . . . . . . . . . . . . . . . . . . . 5-13
5.4.1.3 Stopping Sequences in the Middle . . . . . . . . . . . . . . . . . . . . . . . . . . 5-15
5.4.1.4 Parameterizing Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-16
5.4.1.5 Enhancing the User Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-17
5.4.2 Creating a Sequence Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-19
5.5 Writing Tests Using Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-20
5.5.1 Writing the Simplest Test: Redefining MAIN Sequence body() . . . . . . . . . . 5-20
5.5.2 Writing a Typical Test: Using the Sequence Library . . . . . . . . . . . . . . . . . . . 5-21
5.5.2.1 Writing a Random Test: Setting Weights . . . . . . . . . . . . . . . . . . . . 5-21
5.5.2.2 Modifying an Existing Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-21
5.5.3 Writing a Dedicated Test: Creating a New Sequence Kind . . . . . . . . . . . . . . 5-23
5.5.4 Writing a Unit-Related Test: Using Unit ID . . . . . . . . . . . . . . . . . . . . . . . . . 5-23
5.5.4.1 Unit IDs to Constrain Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-24
5.5.4.2 Hierarchical Unit IDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-24
5.6 Sequence File Organization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-24
5.7 Using Virtual Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-25

vi e Reuse Methodology
Contents

5.7.1 Creating a Virtual Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-26


5.7.2 Passing of Sequence Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-27
5.7.3 Making Other Sequence Drivers Behave . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-28
5.7.4 Sequences for SoC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-28
5.7.5 Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-31
5.8 Advanced Generation-Related Aspects of Sequences . . . . . . . . . . . . . . . . . . . . . . . . . 5-31
5.8.1 Specifying Subtype in do Actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-31
5.8.2 Propagating Parameters in the Sequence Tree . . . . . . . . . . . . . . . . . . . . . . . . 5-33
5.8.3 Migrating Unit Attributes to the Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . 5-33
5.8.4 Generating the Item/Sequence in Advance . . . . . . . . . . . . . . . . . . . . . . . . . . 5-34
5.8.5 Constraining Complex Sequence Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-35
5.9 Implementing Complex Scenarios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-35
5.9.1 Defining Concurrent Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-36
5.9.2 Initializations and Configurations before Starting Sequences . . . . . . . . . . . . 5-37
5.9.3 Interrupt Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-37
5.9.4 Resetting and Rerunning Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-39
5.9.5 DUT-Independent Read/Write Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-41
5.9.6 Controlling the Scheduling of Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-43
5.9.7 Locking of Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-44
5.9.8 BFM-Driver Interaction Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-44
5.9.8.1 Working in PUSH_MODE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-45
5.10 Miscellaneous Advanced Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-46
5.10.1 Disabling Automatic Launch of the MAIN Sequence . . . . . . . . . . . . . . . . . . 5-46
5.10.2 Creating a Common Base for Your Sequences and Sequence Drivers . . . . . 5-46
5.10.2.1 Creating a Common Base for Your Sequences . . . . . . . . . . . . . . . . 5-47
5.10.2.2 Creating a Common Base for Your Sequence Drivers . . . . . . . . . . 5-48
5.10.3 Applying Default Behavior When No Item Is Done . . . . . . . . . . . . . . . . . . . 5-48
5.10.4 Synchronization within a Cycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-49
5.10.4.1 Delaying the Driver Clock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-50
5.10.4.2 Solving Possible Race Conditions . . . . . . . . . . . . . . . . . . . . . . . . . . 5-50
5.10.4.3 Forcing a Reevaluation of the do Action Queue . . . . . . . . . . . . . . . 5-51
5.10.5 Quitting Sequences and Sequences Items . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-52
5.11 Layering of Protocols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-52
5.11.1 Introduction to Layering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-53
5.11.1.1 What Is Layering of Protocols? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-53
5.11.1.2 Layering and Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-54
5.11.2 Styles of Layering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-56

e Reuse Methodology vii


Contents

5.11.2.1 Basic Layering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-56


5.11.2.2 One-to-One, One-to-Many, Many-to-One, Many-to-Many . . . . . . 5-57
5.11.2.3 Different Configurations at Pre-Run Generation and Runtime . . . . 5-58
5.11.2.4 Timing Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-58
5.11.2.5 Data Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-58
5.11.2.6 Complex Inter-Packet Dependencies . . . . . . . . . . . . . . . . . . . . . . . . 5-59
5.11.2.7 Using Virtual Sequence Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-59
5.11.3 Using Layered Sequence Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-60
5.11.3.1 Overview of the Layering Solution . . . . . . . . . . . . . . . . . . . . . . . . . 5-60
5.11.3.2 Introducing Layering into the Low-Layer Sequence . . . . . . . . . . . . 5-62
5.11.3.3 Late Binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-64
5.12 Tracing and Debugging Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-67
5.12.1 trace sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-67
5.12.1.1 trace sequence Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-69
5.12.2 wave sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-70
5.12.3 show sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-70
5.12.4 Customizing Display of Trace and Debug Output . . . . . . . . . . . . . . . . . . . . . 5-71
5.13 Sequence-Related Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-72
5.13.1 start_sequence() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-72
5.13.2 stop() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-73
5.13.3 grab() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-74
5.13.4 ungrab() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-75
5.13.5 is_blocked() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-76
5.13.6 is_grabbed() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-77
5.13.7 current_grabber() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-77
5.13.8 is_relevant() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-78
5.13.9 last() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-78
5.14 Sequence-Related Pseudo-Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-80
5.14.1 in_sequence() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-80
5.14.2 in_unit() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-81
5.15 Sequence Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-82
5.16 Predefined Sequence Kinds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-89
5.16.1 MAIN Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-90
5.16.2 RANDOM Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-90
5.16.3 SIMPLE Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-90
5.17 BFM-Driver-Sequence Flow Diagrams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-91
5.17.1 sequence.start_sequence() Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-92

viii e Reuse Methodology


Contents

5.17.2 do Subsequence Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-93


5.17.3 do Item Flow in Push Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-94
5.17.4 do Item Flow in Pull Mode Using get_next_item() . . . . . . . . . . . . . . . . . . . . 5-95
5.17.5 do Item Flow in Pull Mode Using try_next_item() . . . . . . . . . . . . . . . . . . . . 5-96
5.18 Sequence Deprecation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-96
5.18.1 Method sequence.start() Deprecation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-97
5.18.2 Field sequence Deprecation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-97
5.18.3 Sequence item Deprecation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-99
5.19 Known Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-99
5.19.1 Same Item Cannot Be Used in Two Different Sequences . . . . . . . . . . . . . . . 5-99
5.19.2 Item Children Cannot Be Created with Like Inheritance before Sequence
Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-100
5.19.3 Sequences Are Supported Only from Version 4.1 . . . . . . . . . . . . . . . . . . . . 5-100

6 Messaging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-1
6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-1
6.1.1 Messaging Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-2
6.1.2 Messaging Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-3
6.1.3 Message Logger Struct Deprecation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-4
6.1.4 About This Chapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-5
6.2 Basic Messaging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-6
6.2.1 Basic Message Action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-6
6.2.1.1 Example Message Action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-6
6.2.1.2 Format of Message Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-6
6.2.1.3 Message Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-7
6.2.2 Basic Message Loggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-8
6.2.2.1 message_logger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-8
6.2.2.2 sys.logger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-8
6.2.2.3 Message Tags and Message Destinations . . . . . . . . . . . . . . . . . . . . . 6-9
6.2.2.4 How Loggers Relate to Message Actions . . . . . . . . . . . . . . . . . . . . 6-10
6.2.2.5 Multiple eVCs with Loggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-11
6.2.2.6 Configuring Loggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-12
6.2.3 Basic Messaging Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-13
6.2.3.1 How eVC Writers Configure Messaging . . . . . . . . . . . . . . . . . . . . . 6-13
6.2.3.2 How Integrators Configure Messaging . . . . . . . . . . . . . . . . . . . . . . 6-15
6.2.3.3 How Users Configure Messaging . . . . . . . . . . . . . . . . . . . . . . . . . . 6-15
6.3 The Message Action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-16

e Reuse Methodology ix
Contents

6.3.1 message Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-16


6.3.2 message Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-17
6.3.3 Examples of the Message Action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-17
6.3.4 Output Appearance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-18
6.3.4.1 Short Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-18
6.3.4.2 Long Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-18
6.3.4.3 No Format (none) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-19
6.3.5 Recommended Verbosity Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-19
6.3.6 message_tag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-20
6.4 Message Loggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-20
6.4.1 How Loggers Handle Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-21
6.4.2 Configuring Message Loggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-23
6.5 Messaging Command Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-23
6.5.1 Summary of Messaging Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-23
6.5.1.1 set message Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-24
6.5.1.2 show message Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-25
6.5.2 Detailed Explanation of Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-25
6.5.2.1 set message Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-25
6.5.2.2 show message Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-31
6.6 Messaging Procedural Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-32
6.6.1 Methods for Setting Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-33
6.6.2 Methods for Showing Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-34
6.6.3 Methods Called While Handling Messages . . . . . . . . . . . . . . . . . . . . . . . . . . 6-34
6.6.4 Query Methods for Getting Message Information . . . . . . . . . . . . . . . . . . . . . 6-35
6.7 Configuring Loggers via Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-37
6.7.1 Constrainable Fields and Their Default Values . . . . . . . . . . . . . . . . . . . . . . . 6-38
6.7.2 Using the Constrainable Fields to Configure Loggers . . . . . . . . . . . . . . . . . . 6-38
6.7.3 Constraining Verbosity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-39
6.8 The short_name_path() of a Unit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-40
6.8.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-40
6.8.2 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-40
6.8.3 How short_name_path() Works . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-41
6.8.4 How short_name_path() Is Computed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-41
6.9 Colors for Message Actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-42
6.9.1 Basic Color Handling in Specman . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-42
6.9.2 any_unit.short_name_style() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-43
6.9.3 Coloring Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-43

x e Reuse Methodology
Contents

6.10 Recommended Methodology for the Message Action in eRM eVCs . . . . . . . . . . . . . 6-43
6.10.1 Screen Logger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-44
6.10.2 File Logger(s) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-44
6.10.3 Handling Short Names and Styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-46
6.10.4 Coloring of Whole Message Actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-47
6.10.5 Special Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-48
6.10.6 Tracing Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-48
6.10.7 at_message_verbosity() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-48
6.10.8 Verb Tenses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-49
6.10.9 Soft Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-49
6.10.10 sys.logger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-49
6.10.11 When to Issue Message Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-49
6.10.12 Extending message_logger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-51
6.10.13 show message -actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-51
6.10.14 Scaling the Time Portion of Message Output . . . . . . . . . . . . . . . . . . . . . . . . 6-51

7 eVC Standardization Using eRM Compliance Checks . . . . . . . . . .7-1


7.0.1 Packaging and Name Space Compliance Checks . . . . . . . . . . . . . . . . . . . . . . 7-2
7.0.2 Architecture Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-6
7.0.3 Reset Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-7
7.0.4 Checking Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-9
7.0.5 Coverage Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-10
7.0.6 Sequences Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-10
7.0.7 Messaging Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-12
7.0.8 Monitor Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-13
7.0.9 Documentation Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-13
7.0.10 General Deliverables Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-15
7.0.11 Visualization Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-16
7.0.12 End of Test Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-17
7.0.13 Other Possible Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-17

8 The eRM Utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-1


8.1 Browsing eRM Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-3
8.1.1 The eRM Package Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-5
8.2 Examining Envs and Units . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-5

e Reuse Methodology xi
Contents

8.2.1 The Env Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-8


8.2.2 The Stripe Chart Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-9
8.2.3 Customizing Visualization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-11
8.2.3.1 Changing the Visualized Information in the Env Window . . . . . . . 8-12
8.2.3.2 Changing the HTML Template for the Env Window . . . . . . . . . . . 8-13
8.2.3.3 Adding Information to the Stripe . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-13
8.2.3.4 Showing User-Defined Items as Stripes . . . . . . . . . . . . . . . . . . . . . 8-14
8.2.3.5 Showing Sub-Items as Stripes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-14
8.2.3.6 Customization-Related Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-15
8.3 Controlling Messaging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-16
8.3.1 Controlling Message Loggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-17
8.3.1.1 The Logger Destinations Window . . . . . . . . . . . . . . . . . . . . . . . . . . 8-19
8.3.2 Controlling Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-20
8.4 Using the eDoc Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-21
8.4.1 The eDoc Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-22
8.4.2 Generating eDoc Reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-23
8.4.3 show doc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-24

9 Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-1
9.1 Supporting Multiple Resets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-1
9.1.1 Reset Assumptions and Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-1
9.1.1.1 Primary Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-1
9.1.1.2 Secondary Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-2
9.1.2 Reset Methodology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-2
9.1.3 rerun() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-4
9.1.4 Reset Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-5
9.2 Instance Names and IDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-6
9.2.1 About Instance Names and IDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-6
9.2.2 Enumerated Logical Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-7
9.2.3 Scalar IDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-8
9.2.4 Use of Instance Names and IDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-8
9.2.5 Instance Names: XBus Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-9
9.2.5.1 eVC Developer Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-9
9.2.5.2 eVC User Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-11
9.3 Adding Scoreboards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-12
9.3.1 What Is a Scoreboard? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-12
9.3.2 Memory Access Scoreboards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-13

xii e Reuse Methodology


Contents

9.3.3 End-to-End Scoreboards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-13


9.3.4 End-to-End Scoreboard Hooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-13
9.3.5 Scoreboard Recommendations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-14
9.4 Visualization: Creating User-Friendly Reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-15
9.5 Status Coordination and End of Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-15
9.5.1 Introduction to Status Coordination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-15
9.5.1.1 General Requirement for Status Coordination . . . . . . . . . . . . . . . . . 9-15
9.5.1.2 Requirements for End-Of-Test Handling . . . . . . . . . . . . . . . . . . . . 9-16
9.5.1.3 Overview of Status Coordination Solution . . . . . . . . . . . . . . . . . . . 9-16
9.5.2 Objection Mechanism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-17
9.5.2.1 objection_kind enum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-18
9.5.2.2 Objection Counter and Objection Total . . . . . . . . . . . . . . . . . . . . . . 9-18
9.5.2.3 Methods of any_unit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-18
9.5.2.4 Behavior upon quit() and rerun() . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-20
9.5.2.5 Debugging Aids . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-21
9.5.3 End-Of-Test Mechanism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-22
9.5.3.1 Basic End-Of-Test Mechanism . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-23
9.5.3.2 End-Of-Test Handling Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-23
9.5.3.3 Converting Old Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-25
9.6 Encrypting Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-25
9.6.1 How Encryption Works . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-26
9.6.2 How Much To Encrypt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-26
9.6.3 Adding Extra Debugging Aids to Encrypted Packages . . . . . . . . . . . . . . . . . 9-27
9.6.4 Protecting Non-Encrypted Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-27
9.6.5 Publishing the Interface of Encrypted Files . . . . . . . . . . . . . . . . . . . . . . . . . . 9-27

10 Golden eVCs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10-1


10.1 XBus eVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-1
10.2 XSerial eVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2
10.3 XSoC eVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2
10.4 ATM eVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2
10.5 eVC Environment: Flexibility vs. Rigidity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-3
10.5.1 How to Determine Environment Flexibility . . . . . . . . . . . . . . . . . . . . . . . . . . 10-3
10.5.2 Setting Environment Flexibility Using Generation Order . . . . . . . . . . . . . . 10-4

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Index-1

e Reuse Methodology xiii


Contents

xiv e Reuse Methodology


1 Introduction
This chapter includes a general introduction to this manual, to eRM, and to eVCs. It contains the
following sections:

• “About This Book” on page 1-1


• “About the eRM Release Library (erm_lib)” on page 1-2
• “About eVCs” on page 1-3
• “Conventions in This Manual” on page 1-6

1.1 About This Book


This manual is all about maximizing reusability of verification code written in e. eRM (e Reuse
Methodology) ensures code reusability by discussing the best known methods for designing, coding,
and packaging e code as reusable components.

Most of the guidelines herein apply to any scale or type of verification environment. Since e Verification
Components (eVCs) are an ultimate form of reusable verification environment, the majority of this book
relates to creating eVCs.

A key factor for reusing code is arranging it as an independent and easy-to-use code package. When
developing verification code in e, the reusable package is typically organized as an eVC (e Verification
Component). For this reason, eRM speaks a lot about eVCs: standardizing eVC development practices,
defining a common eVC user model, and ensuring that eRM-compliant eVCs are plug-and-play. In
short, this manual also explains how to develop verification components that will provide eVC users
with consistent and superior verification experiences.

The intended audience for this book includes eVC developers, verification environment developers, and
technical managers responsible for these environments.

Following is a brief description of each chapter in this manual.

e Reuse Methodology 1-1


Introduction
About the eRM Release Library (erm_lib)

Chapter 1 “Introduction” This chapter


Chapter 2 “Verification Packages” How to organize verification
components/utilities and how to ship them
Chapter 3 “eVC File Organization” How to organize eVC files and directories
Chapter 4 “Typical eVC Architecture” How to model eVCs
Chapter 5 “Sequences: Constructing Test How to use Specman sequences in a uniform and
Scenarios” efficient way
Chapter 6 “Messaging” How to create standard messages
Chapter 7 “eVC Standardization Using eRM How to maintain a high standard and uniformity
Compliance Checks” for eVCs
Chapter 8 “The eRM Utility” How to use the eRM Utility, a graphical user
interface with tools that facilitate various
eRM-related tasks
Chapter 9 “Reference” Detailed discussion of specific topics
Chapter 10 “Golden eVCs” eVCs that serve as role models for e Reuse
Methodology

1.2 About the eRM Release Library (erm_lib)


The eRM library (erm_lib) contains all of the deliverables associated with eRM— infrastructure
utilities, examples, documentation, and more.

The library includes the following packages and subdirectories:

evc_util This package includes the infrastructure syntax, types, and utilities needed
for writing eVCs. It is the core module of the eRM library.
Documents This directory contains all of the main eRM documentation. It also contains
(in the erm_docs eRM presentations in PDF format.
directory)
Golden eVCs These are example eVC packages, constructed according to eRM guidelines.
They are designed to teach eRM methodology and concepts and to provide a
starting point for eVC development. Three examples are included. One
represents a bus-based environment (vr_xbus), one represents a serial data
stream environment (vr_xserial), and one represents an SoC environment
that incorporates vr_xbus and vr_xserial (vr_xsoc). You can find the three
golden eVCs in directories with their respective names (vr_xbus, vr_xserial,
vr_xsoc).

1-2 e Reuse Methodology


Introduction
About eVCs

Example These are minipackages that demonstrate use of some specific features
directories provided by the eRM library, such as sequences and packaging. They all
have an ex_ prefix (for example, ex_atm, ex_soc, ex_c_bus).
Labs This directory includes labs designed to teach eRM.
(in the lab directory)
vt_util This is the eRM Utility package.
Shareware These packages offer useful functionality. They are, however, often provided
packages at a lower level of productization and support than the official utilities. The
shareware packages are all marked with a shr_ prefix (for example,
shr_install).
Templates This directory contains templates for eVC user guides (in FrameMaker and
(in the templates MS Word formats) and for eVC training classes (in PowerPoint format).
directory)

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

1.3 About eVCs


This section includes:

• “What Are eVCs?” on page 1-3


• “eVCs vs. Regular Verification Environments (VEs)” on page 1-4
• “eVCs as Plug-and-Play Components” on page 1-5
• “eVC Reuse Requirements” on page 1-5

1.3.1 What Are eVCs?


An eVC™ is an e Verification Component. It is a ready-to-use, configurable verification environment,
typically focusing on a specific protocol or architecture (such as PCI Express, Ethernet, AHB, or USB).

Each eVC consists of a complete set of elements for stimulating, checking, and collecting coverage
information for a specific protocol or architecture. You can apply the eVC to your device under test
(DUT) to verify your implementation of the eVC protocol or architecture. eVCs expedite creation of a
more efficient test bench for your DUT. They can work with both Verilog and VHDL devices and with
all HDL simulators that are supported by Specman®.

e Reuse Methodology 1-3


Introduction
eVCs vs. Regular Verification Environments (VEs)

You can use an eVC as a full verification environment or add it to a larger environment. The eVC
interface is viewable and thus can be the basis for user extensions. We recommend doing such
extensions in a separate file. Maintaining the eVC in its original form facilitates possible upgrades.

eVC implementation is often partially encrypted, especially in commercial eVCs where authors want to
protect their intellectual property. Most commercial eVCs require a specific feature license to enable
them.

This manual takes a fairly liberal approach to the question of what is an eVC. For the purposes of this
manual, an eVC is a significant, productized, modular piece of e code that can be used to verify
something and that has a single owner who is responsible for it (supporting it and possibly selling it).

Notes
• An eVC can depend on another eVC. For example, there could be a TCP/IP eVC that uses (imports)
an Ethernet eVC. That TCP/IP eVC could still be developed and sold separately.
• An eVC must be significant and productized. These are not exact terms, but clearly a 200-line
scoreboard module does not qualify as an eVC. eVCs are usually 5,000 to 20,000 lines in size, and
they embody significant knowledge and work (so that people would be willing to pay money for
them).

Following is a partial list of possible kinds of eVCs:

• Bus-based eVCs (such as PCI and AHB)


• Data-communication eVCs (for example, Ethernet, MAC, Datalink)
• CPU/DSP eVCs
• Higher-level protocol eVCs (TCP/IP, HTTP). These usually sit on top of other eVCs.
• Platform eVCs (that is, an eVC for a specific, reusable SoC platform, into which you plug eVCs of
various cores).
• Compliance test-suite eVCs. These are tests (and perhaps coverage definitions and more) that
demonstrate compliance to a protocol. For example, there could be a PCI compliance eVC in addition
to the basic PCI eVC.
• HW/SW co-verification eVCs, such as an eVC dedicated to verifying a HW/SW environment using
a particular RTOS/CPU combination.

1.3.2 eVCs vs. Regular Verification Environments (VEs)


The distinction between an eVC and a modular, well written verification environment (VE) is fuzzy. The
main difference is that an eVC is meant to be used in more than one setting.

1-4 e Reuse Methodology


Introduction
eVCs as Plug-and-Play Components

Regardless of whether the combined VE is itself an eVC or not, when we integrate n eVCs into a VE, we
have n+1 pieces: the n eVCs and the explicitly added code for the VE. The plug-and-play considerations
described below relate to all n+1 items.

For example, there should be no name collisions between eVCs, but there should also be no name
collisions between any of the eVCs and the VE. Therefore names like pci_checks.e would not be
appropriate, because users might want them too.

Note The recommendations in this manual represent the best practices for those using Specman.
Therefore, they apply not just to eVCs but also to regular VEs. For example, unified tracing (as is
recommended for plug-and-play eVCs) is very useful when applied to blocks within a big VE, even if
neither the blocks nor the VE are ever meant to be reused.

1.3.3 eVCs as Plug-and-Play Components


Ideally, eVCs must be plug-and-play components in the sense that a new verification environment can
be constructed from eVCs that were not initially planned to work together. Not only that, it should be
possible to do this hierarchically. In other words, it should be relatively easy to construct the combined
VE also as an eVC, which in turn could be plugged into yet a bigger VE.

To enable this capability, eVCs (and indeed general VEs, which could potentially be turned into eVCs)
should be written as if they are part of a universal verification environment.

Following are the benefits of making eVCs plug-and-play:

• Promotes code sharing:


• Within companies
• Between companies
• Offers customers a convenient, ready-to-use product
• Makes eVC creation easier and faster

1.3.4 eVC Reuse Requirements


The following requirements are essential for eVC reuse. These requirements are all from the perspective
of the eVC user. They translate into recommendations for the eVC writer.

Note All of the following recommendations are described in much greater detail throughout the rest of
this manual.

e Reuse Methodology 1-5


Introduction
Conventions in This Manual

No interference between eVCs • No name space collision


• No complex SPECMAN_PATH or directory dependencies
• Handling dependencies on common modules
• No dependencies on different versions of Specman and
utilities
• No timing dependencies
• No dependencies on global settings
Common look and feel, similar • Common way to install eVCs
activation, similar • Common way to patch eVCs
documentation • Common tracing and debugging
• Handling DUT errors
• Getting eVC identification
• Waveform viewer data
• Custom visualization
• Common way of specifying simulator-specific material
• Common way to do backdoor initialization
• Common programming interface to standard blocks
• Common eVC taxonomy
• Common style of documentation
Support for combining eVCs • Common way to configure eVCs
(control, checking, layering, and • Common way to write tests
so on) • Common way to create sequences
• Common way to do checking
• Combined determination of end of test
• Common way to do layering of protocols
• Common way to do combined coverage
Support for modular debugging • Understanding combined constraints
• Reconstructing the behavior of a single eVC in the
verification environment
Commonality in implementation • Common data structures
• Common eVC testing methodology
• Common way to use ports and packages

1.4 Conventions in This Manual


This manual uses variations in typefaces to help you locate and interpret information easily. These type
variations are explained in Table 1-1.

1-6 e Reuse Methodology


Introduction
Conventions in This Manual

Table 1-1 Document Conventions

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

[ ] 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)

e Reuse Methodology 1-7


Introduction
Conventions in This Manual

Table 1-1 Document Conventions (continued)

Typeface Represents

vrst-tool> Denotes the prompt for the Verisity tool you are running, including
Specman Elite, vManager, SpeXsim, or SpeXtreme.

C1>, C2>, … Denotes the Verilog simulator prompt.

> Denotes the VHDL simulator prompt.

% Denotes the UNIX prompt.

1-8 e Reuse Methodology


2 Verification Packages
This chapter explains how to organize verification components into packages and how to ship them. For
the purposes of this chapter, the verification components can be of any sort—eVC, shareware
component, and so on.

This chapter includes the following sections:

• “What Is a Verification Component Package” on page 2-1


• “Package-Related Naming Conventions” on page 2-3
• “Directory Structure” on page 2-5
• “Accessing Files” on page 2-10
• “Handling Package Versions” on page 2-12
• “PACKAGE_README.txt File” on page 2-19
• “any_env Unit” on page 2-23
• “show packages Command” on page 2-26
• “Recommend nations” on page 2-28

2.1 What Is a Verification Component Package


A package is a directory structure containing all relevant material for verifying a particular kind of
component. By “packaging” all relevant material into one directory, this enables reuse of the verification
environment. By convention, packages have naming standards by which you can easily see the name
and version of the verification environment. Packages typically have other standards, such as a common
installation procedure. This section describes these standards, which conform to e Reuse Methodology
(eRM) guidelines.

e Reuse Methodology 2-1


Verification Packages
Packages as e Concept

Each reusable verification component should be packaged in its own directory, which:

• Is separately released and versioned.


• Contains e code and related files.
• Has a standard structure and a standard-format PACKAGE_README.txt file.
These package directories are the basic unit for sending verification components from place to place.

A package could contain an eVC, a shareware utility, and so on.

2.1.1 Packages as e Concept


From Specman 4.1, packages are a concept in the e language. This includes:

• Package syntax (see “package package-name” in the e Language Reference).


• Ability to hide package private entities (as part of the general e encapsulation solution).
Each package directory contains one or more e packages.

Packages can be encrypted. Encrypted packages can also be licensed.

2.1.2 Kinds of Packages


There are two main kinds of packages:

• Environment packages
These are packages that define an env root unit (a child of any_env, see below), which can be
instantiated in your verification environment.
Env packages can be divided further into eVC packages and shareware env packages, such as a
small ATM shareware.
• Utility packages
These are packages that do not define a unit to be instantiated but rather are helpful utilities that
supply various services, for example, a visualization utility.
Utility packages also divide into shareware utilities and officially supported utilities. One specific
officially supported utility package is the evc_util package, which should be imported by each eVC
(see “evc_util Package” on page 2-4).

There may be other kinds of packages. ESI adaptors, CE tools, and more may end up being bundled as
packages, thus enjoying the various facilities packages have (such as an easy way to see their
names/titles/versions, standard installation procedure, and so on).

2-2 e Reuse Methodology


Verification Packages
Package-Related Naming Conventions

2.2 Package-Related Naming Conventions


This section discusses naming conventions for files and types as they relate to packages. Other naming
conventions will be discussed in other documents.

Each package has a package name. Because we want to mix and match packages from various of
sources, we should strive to make package names unique. (Two packages cannot be loaded together if
they have the same name.)

We use the notation package to denote the package name (for example, “vr_xbus”), and PACKAGE to
denote the uppercase version of it (for example, “VR_XBUS”).

By convention, all e file names in the package should start with the package name. For example, the top
file could be:
package_top.e // for example, vr_xbus_top.e

Furthermore, all types should start with the package name. For example:
package_cell
Note Fields in package-defined structs are not recommended to start with the package name. For
example:
type vr_xbus_kind: [x, y, z];
struct vr_xbus_transaction {
kind: vr_xbus_kind;
};

This section includes:

• “Choosing a Package Name” on page 2-3


• “evc_util Package” on page 2-4

2.2.1 Choosing a Package Name


Package names should be clear, short, and unique. This is not an easy set of requirements to reconcile.

We suggest that the package name consist of two parts:


company-prefix_proper-name

The company-prefix is a two to four letter prefix, such as “vr” for Verisity and “arm” for ARM. We
suggest contacting erm_admin@verisity.com to make sure your preferred prefix is unique.

The proper-name is the name of the corresponding protocol, and so on, for example, “atm”.

e Reuse Methodology 2-3


Verification Packages
evc_util Package

We recommend that the package name be all lowercase. It should follow the same convention as a name,
that is, start with a letter and contain only letters, digits, and underscores.

Some prefixes have special meaning. Table 2-1 on page 2-4 lists some general reserved prefixes.

Table 2-1 General Reserved Prefixes

Prefix Reserved For

evc Various general utilities supplied by Verisity, such as evc_util.

erm Various eRM utilities supplied by Verisity.

sn Internal Specman entities.

rf Specman reflective facility.

ex Small, example packages.

shr Shareware that does not use a company name prefix. For example, if a user wants to
donate a register creation package as shareware, s/he can call it “shr_register”.

Package Name Assignment


Shareware package names get assigned by putting the package in the Verification Vault. You cannot put
a package in the Verification Vault if the name is already used.

Package Name Examples


Some examples of package names are:

• vr_pci (Verisity PCI eVC)


• arm_act (ARM ACT package)
• shr_atm (ATM shareware)

2.2.2 evc_util Package


The evc_util package is a special package containing various utilities. The top file of each package
should import it before importing anything else.
import evc_util/e/evc_util_top;
Note Some of the utilities in evc_util will end up in Specman itself. This, however, should not be a
problem for the package writer. Each new release of Specman will come with an updated (and perhaps
smaller) evc_util, thus shielding the package writer from changes.

2-4 e Reuse Methodology


Verification Packages
Directory Structure

2.3 Directory Structure


A package contains not just e code, but also related elements such as documentation, examples, and so
on. Thus, a package is really a directory structure containing all relevant material.

When installed, packages reside in library directories (libraries, for short) and must contain a file called
LIBRARY_README.txt. Libraries are then named in the $SPECMAN_PATH. Thus, a library is any
directory in your $SPECMAN_PATH that contains a file called LIBRARY_README.txt.

Figure 2-1 Packages Grouped Under Libraries


$SPECMAN_PATH
/usr/joe/private_lib/ : /project/specman/proj_lib/ : /cad/evc_lib/

/usr/joe/private_lib/
LIBRARY_README.txt /project/specman/proj_lib/
LIBRARY_README.txt /cad/evc_lib/
co_atm/ LIBRARY_README.txt
PACKAGE_README.txt vr_ahb/ shr_visualizer/
demo.sh PACKAGE_README.txt PACKAGE_README.txt evc_util/
e/ demo.sh demo.sh
docs/ PACKAGE_README.txt
e/ e/ demo.sh
examples/ docs/ docs/
verilog/ e/
examples/ examples/ docs/
... misc/ examples/

For example, your $SPECMAN_PATH could contain:


...:/usr/joe/private_lib:/project/specman/proj_lib:/cad/evc_lib

In this example, $SPECMAN_PATH contains three package libraries: a private library, a project-wide
library, and a company-wide library. These libraries will be searched in that order (as is usually the case
with $SPECMAN_PATH).

Contents of some of these example libraries are:

/project/specman/proj_lib
• LIBRARY_README.txt
• vr_ahb/
• PACKAGE_README.txt
• demo.sh
• e/

e Reuse Methodology 2-5


Verification Packages
Directory Structure

• docs/
• examples/
• misc/
• evc_ve
• vr_pci/
• PACKAGE_README.txt
• demo.sh
• e/
• docs/
• examples/
• misc/
• evc_ve
• ...

/usr/joe/private_lib/
• LIBRARY_README.txt
• shr_atm/
• PACKAGE_README.txt
• demo.sh
• e/
• examples/
• shr_visualizer/
• PACKAGE_README.txt
• demo.sh
• e/
• ...
Using the example $SPECMAN_PATH as described above, if you type the following, in Specman:
load shr_atm/e/shr_atm_top.e

this loads /usr/joe/private_lib/shr_atm/e/shr_atm_top.e even if there is a shr_atm directory in proj_lib or


evc_lib. This is because private_lib comes first in $SPECMAN_PATH.

Note If multiple libraries in your $SPECMAN_PATH contain the same package name, then only the
first one in $SPECMAN_PATH is used. Use the show package -on_disk -full command to display
redundant packages.

This section includes:

• “Library Directory” on page 2-7

2-6 e Reuse Methodology


Verification Packages
Library Directory

• “Package Directory” on page 2-7

2.3.1 Library Directory


The library directory in the $SPECMAN_PATH usually contains the following:

• LIBRARY_README.txt file
This file must exist. By convention, it contains a description of the library on a single line, as
follows:
* Title: This is the project-wide shareware library.
Note that this construction is similar to the title line of the PACKAGE_README.txt file described
below.
• Various package directories
The package directories, one per package, are described in “Package Directory” below.
• A versions directory
By convention, a directory called versions should exist in a library directory. Whenever a new
version of the package arrives, it is first untarred as a subdirectory of the versions directory and
then copied under the package name to the library directory.

2.3.2 Package Directory


The recommended content of the package directory is the following:

• “PACKAGE_README.txt File” on page 2-7


• “demo.sh File” on page 2-8
• “e Directory” on page 2-8
• “Docs Directory” on page 2-8
• “Examples Directory” on page 2-8
• “evc_ve Directory” on page 2-9
• “Other Directories” on page 2-10

2.3.2.1 PACKAGE_README.txt File


Each package directory must contain a file called PACKAGE_README.txt (uppercase name with a
lowercase txt extension). This applies for every package—eVC, shareware, utility, and so on.

e Reuse Methodology 2-7


Verification Packages
Package Directory

For a detailed description of this file, see “PACKAGE_README.txt File” on page 2-19.

2.3.2.2 demo.sh File


This file, which resides directly in the package directory, should run a full demo of the package. It is
important to make the demo as complete as possible.

To have the demo run, you should be able to type the following command from any work directory:
% 'sn_which.sh package/demo.sh'

Usually, there will be several examples in the package/examples directory. demo.sh should be able to
run one of them (perhaps loading an e file called demo.e).

Note demo.sh can use the predefined sn_which.sh shell script (see “sn_which.sh Shell Script” on page
2-11) to avoid setting the $PATH environment variable (assuming $SPECMAN_PATH is set correctly to
go through the desired library directories).

2.3.2.3 e Directory
This directory contains all essential e code files belonging to the package. These could all reside flatly in
this directory, or be organized in subdirectories within the e directory as needed.

The e directory should contain the package_top.e file, which imports the other necessary files. It can
either import all necessary files, or it can import other top files of the package that, in turn, import all
necessary files.

The package writer must decide whether to have only downward imports (that is, from top files to other
files) or to have each file import all files it depends on.

See “Accessing Files” on page 2-10 for an explanation of how to write the actual import actions.

2.3.2.4 Docs Directory


This directory contains the documentation for the package. The documentation can be in any format; but
PDF, ASCII, and HTML are probably the best because they are platform independent.

Note Put the release notes in this directory.

2.3.2.5 Examples Directory


All examples reside in this directory. Examples can contain e files, HDL files, shell scripts and other
files. The examples directory should also contain sample configuration files that can be modified and
used by clients.

2-8 e Reuse Methodology


Verification Packages
Package Directory

If an example consists of more than one file, it may make sense to create subdirectories for each
example.

Examples should import package files using the package-relative notation to make the package usable
from any location. For example, the file test1.e in the foo package might look like this:
<'
import foo/e/foo_top;

extend foo_packet {
...
};
'>

See “Using Package-Relative File Names” on page 2-10 for more information.

Notes
• Files and structs in the examples directory do not have to follow the naming conventions. They are
not really part of the package e code.
• The demo.sh file described in “demo.sh File” on page 2-8 does not reside in the examples directory,
but normally it imports files from the examples directory.

2.3.2.6 evc_ve Directory


Each eVC package should include a test suite to verify the main features of the eVC. The test suite
should be in a top-level directory named evc_ve (eVC verification environment), and include the
following:

• Coverage plan: Documentation on the coverage goals of the eVC verification


• Test descriptions: Description of the tests, including work mode and features activated
• Tests: A few random tests providing full coverage
• Sequence definitions: Sequences defined and used for eVC verification
• Coverage results: From the test suite run by the developer
• Script to activate self-verification
• Script to display coverage results
Typically, the number of tests achieving full coverage is not large. So the entire self-verification
environment can be maintained in a single directory. However, if the number of tests is large, they
should be divided into subdirectories according to their subject.

e Reuse Methodology 2-9


Verification Packages
Accessing Files

Verification for SoC


If an SoC package uses other eVCs, the SoC verification environment can use tests from the used
packages. The SoC evc_ve directory should have only the tests relating to the SoC. Those tests will
typically use sequences from the sequence libraries of the used eVCs.

2.3.2.7 Other Directories


Other directories can be created as needed, such as verilog/, vhdl/, misc/, and so on.

Note If the Verilog files are part of a particular example, they should be under that example in the
examples/ directory.

2.4 Accessing Files


This section includes:

• “Using Package-Relative File Names” on page 2-10


• “Package Shadowing” on page 2-11
• “Importing Files within the Same e Source Directory” on page 2-11
• “sn_which.sh Shell Script” on page 2-11

2.4.1 Using Package-Relative File Names


In general, we recommend accessing package files and directories from within Specman using
package-relative file names, that is, file names that start with the package/ directory name. For example:
import vr_xbus/e/vr_xbus_top;

@ex_atm/load.ecom

This is different from the previous way of organizing eVCs. Previously, you had to set your
$SPECMAN_PATH for source and doc directories of each eVC you used. This meant that you had to
change $SPECMAN_PATH whenever you wanted to use a new verification component. This could be
tedious if you wanted to explore many utilities or pieces of shareware.

Using package-relative names, any file in any library in your $SPECMAN_PATH is equally accessible.
This means that you can use a new eVC by including it in a library. Use the show packages -on_disk
command to see the packages that can be loaded.

2-10 e Reuse Methodology


Verification Packages
Package Shadowing

2.4.2 Package Shadowing


If you want to try a new version of a package without disrupting other people who are using an older
version of the same package, put the new version in a library that is mentioned earlier in your
$SPECMAN_PATH. In most cases, this will be a private library.

For example, if your $SPECMAN_PATH contains this set of libraries:


…:/usr/joe/private_lib:/project/specman/proj_lib:/cad/evc_lib

You can put the new version of the package foo under private_lib, and it will be found first. (The other
version of foo later in the $SPECMAN_PATH is “shadowed” by the first one and is not used.)

Assume that foo needs bar, and imports it in a package-relative way:


import bar/e/bar_top;

Then, it will find the old bar, unless you also put a newer version of bar in your private_lib.

2.4.3 Importing Files within the Same e Source Directory


Importing files in another package should always be done using the package-relative notation.

Importing files within the same directory tree (for example, the e directory) can be done either using
package-relative names, or (more conventionally) assuming the directory of the importing file. Thus, the
file bar/e/bar_top.e could import files as follows:
import xx; // xx.e is in same directory as importing file
import yy; // yy.e is in same directory as importing file
import checks/cell_check; // cell_check.e is in e/checks/

Never use the “../xx” notation for relative pathnames.

2.4.4 sn_which.sh Shell Script


Package-relative file names work fine for Specman but may be a problem in the shell, because the shell
does not know about $SPECMAN_PATH. In this cases, use a special script called sn_which.sh.

“sn_which.sh file” looks for file in (and only in) your $SPECMAN_PATH and writes the full path name
to stdout. If file is not found, an error message is written to stderr. For example, “sn_which.sh foo/bar.x”
would print “/usr/me/shareware/foo/bar.x”, assuming “/usr/me/shareware” is in your
$SPECMAN_PATH and this is the first such match.

Following are some examples of using sn_which.sh:


`sn_which.sh foo/misc/doit.sh` my_param

e Reuse Methodology 2-11


Verification Packages
Handling Package Versions

cc `sn_which.sh foo/c_files/xx.c`
Note sn_which.sh is limited to searching for files in your $SPECMAN_PATH. It ignores all other
features like the Specman specman -pre_command.

2.5 Handling Package Versions


This section describes how to version packages and handle package version dependencies. It includes
these sections:

• “Where the Version Number Appears” on page 2-12


• “Shipping New Versions of a Package” on page 2-13
• “Declaring Dependencies on Specman Version and Other Packages” on page 2-15
• “Using the Package Compatibility Analyzer” on page 2-16

2.5.1 Where the Version Number Appears


Each time you release a new version of a package, it should be accompanied by a new version number.
Typically, the version number is a two-part number, including a major and minor release number.

The version number is seen in three places:

• PACKAGE_README.txt file, as an ASCII name


• package_top.e file, as a define
• Tar file/directory
In all three places, the version number should match.

In PACKAGE_README.txt File (ASCII Name)


Examples:
Version: 3.1

Version: 0.2 (Experimental)


Note As this is an ASCII name, you can add extra text to describe the release, for example,
“(Experimental)” illustrated above.

2-12 e Reuse Methodology


Verification Packages
Shipping New Versions of a Package

In package_top.e File (Define)


Examples:
define VR_XBUS_VERSION_3_1;

define VR_XBUS_VERSION_0_2;
Note For each major release, use the OR_LATER statement in the define. For example:
define VR_XBUS_VERSION_3_0_OR_LATER;

When you define several major releases, the OR_LATER defines build up. Thus, vr_xbus_top.e might
look as follows:
vr_xbus_top.e - Top file for the vr_xbus package

<'
define VR_XBUS_VERSION_3_1;
define VR_XBUS_VERSION_2_OR_LATER;
define VR_XBUS_VERSION_3_OR_LATER;

import evc_util/e/evc_util_top;

import vr_xbus_types;
...
'>

Name of Tar File/Directory


In the library/versions directory:
library/versions/
vr_xbus_version_3_1/
vr_xbus_version_3_1.tar.gz
Note The name of the directory is the same as the name of the define except that it is all in lowercase.

2.5.2 Shipping New Versions of a Package


After creating a new version of the package and testing it, you need to ship it.

To ship a new version of your package:

1. Make sure that the information in your PACKAGE_README.txt file and any other documentation
such as release notes or user guide is up to date. In particular, pay attention to the data following the
“Version” and “Modified” headers.

e Reuse Methodology 2-13


Verification Packages
Shipping New Versions of a Package

2. Pack the new version of your package, using the approach in either “Simple Method to Pack the
Version” on page 2-14 or “Robust Method to Pack the Version” on page 2-14.

Note There is an install/release scripts package in the shr_install/docs directory of the erm_lib.
You can use these scripts to automate the processes of releasing and installing packages.

3. Distribute the new version of your package using whatever means you prefer, such as by uploading
it to your FTP site or emailing it to users.

2.5.2.1 Simple Method to Pack the Version


This approach uses the same directory names for all versions.

• To pack a new version of the package:


Tar the package directory and gzip it. Then give the result an appropriate name, for example,
vr_xbus_version_3_0.tar.gz.
• To unpack the new version of the package:
Put the tar.gz file in some library directory. Then unzip and untar it to make the new version
available.
Note The disadvantage of using this method is that there is no easy way for the user to keep multiple
versions of these kinds of packages.

2.5.2.2 Robust Method to Pack the Version


This approach uses different directories for different versions.

Versions Directory
By convention, you should have a directory called versions under the library directory. Whenever a new
version of the package arrives, it is first untarred as a subdirectory of the versions directory and then
copied under the package name to the library directory.

Packing a New Version of the Package

To pack a new version of the package:

1. Copy the directory containing one or more packages into the corresponding versioned directory
(called, for example, package_version_num_num). For example:
% cp -r vr_xbus ../versions/vr_xbus_version_3_1

2-14 e Reuse Methodology


Verification Packages
Declaring Dependencies on Specman Version and Other Packages

Note We suggest the convention of putting the versioned directory in the “versions” subdirectory
of the library.

2. Tar that versioned directory from the directory just above it, and gzip the result. For example, if the
package you want to make resides in somepath/versions/vr_xbus_versions_3_1:
% cd somepath/versions
% tar xvf vr_xbus_version_3_1.tar vr_xbus_version_3_1
% gzip vr_xbus_version_3_1.tar

To unpack the new version of the package:

1. Save the gzipped, tarred file to the “versions” directory of the library to which you want to add it.

2. Unzip and untar the file. For example:


% cd ~/my_lib/versions
% gzip -d vr_xbus_version_3_1.tar.gz
% tar xvf vr_xbus_version_3_1.tar
This creates a directory with the name of the tar file in the directory containing the tar file.

3. Copy the versioned directory to the library under the package name. For example.
% cd ~/my_lib
% cp -r versions/vr_xbus_version_3_1 vr_xbus
Alternatively, you can create a symbolic link from your library to your versions directory rather
copying the directory.
Assuming that library is in your $SPECMAN_PATH, you can now run the demo from anywhere.
For example:
% cd ~/work
% ~/my_lib/vr_xbus/demo.sh

2.5.3 Declaring Dependencies on Specman Version and


Other Packages
eVC providers declare the dependency rules for a package in the PACKAGE_README.txt file. The
dependency rules specify the necessary version(s) for Specman and any other required packages.

To declare dependencies on Specman version and other packages:


• In the PACKAGE_README.txt file, declare each dependency on a separate line under the heading
“* Requires”. For example:
* Requires:
specman 4.1

e Reuse Methodology 2-15


Verification Packages
Using the Package Compatibility Analyzer

evc_util 0.7
vr_xbus .. 1.1
vr_xserial 0.9 ..
vt_util 0.5 .. 1.2
Note If the version field of a required package is left empty, any version will be accepted.

For an explanation of the dependency syntax, see “Version Numbers and Ranges” below.

2.5.3.1 Version Numbers and Ranges


Versions numbers are specified using two or three decimal numbers x.y or x.y.z. Non-numeric characters
should not be used in the specification of a version or version range, because version numbers are
truncated at the first non-numeric character. So, for example, 4.12b3.3 is treated as 4.12.

To specify a closed range of versions:


• Insert two dots between the low and the high version.
For example:
3.1 .. 4.7.1 //Indicates all versions from 3.1 up to 4.7.1
//(inclusive)

To specify an open-ended range of versions:


• Place two dots as appropriate before or after the low or high end of the range.
For example:
3.0 .. //All versions from 3.0 onwards
.. 4.7 //All versions up to and including 4.7

To specify a list:
• Separate the list members with commas and contain them all inside brackets.
For example:
{2.5,3.0 .. 3.12,4.0 ..} //Only the specified versions and ranges
Note Range lists can include both specific versions and ranges of versions.

2.5.4 Using the Package Compatibility Analyzer


By default, whenever a package is loaded, the Package Compatibility Analyzer checks the package’s
dependencies, declared in the PACKAGE_README.txt file. In case of inconsistencies, the Package
Compatibility Analyzer produces error or warning messages.

2-16 e Reuse Methodology


Verification Packages
Using the Package Compatibility Analyzer

The Package Compatibility Analyzer runs automatically as part of the evc_util package. It can run in
either interpreted or compiled mode. You can also disable it.

• To disable the Package Compatibility Analyzer:


Comment out the definition of VR_PACKAGE_COMPATIBILITY_ANALYZER in the
evc_util_top.e file.
// define VR_PACKAGE_COMPATIBILITY_ANALYZER
Note Disabling the Package Compatibility Analyzer only takes effect the next time that the evc_util
package is loaded.

2.5.4.1 How the Package Compatibility Analyzer Works


The Package Compatibility Analyzer starts working right after you load its module. The first time that
the analyzer is activated, it checks the compatibility of all loaded packages (including compiled
packages). If you have already loaded packages with unsatisfied dependencies or if you subsequently
load packages with unsatisfied dependencies, then the analyzer notifies you of the incompatibility.

Table 2-2 describes the notifications generated by the Package Compatibility Analyzer.

Table 2-2 Package Compatibility Analyzer Notifications

Default
Condition Notification Severity

Package x is not available in the PACKAGE_NOT_FOUND: Package x cannot Warning


SPECMAN_PATH be found

The version number of package x PACKAGE_VER_INCOMP: Package x version Warning


is not within the required range y is incompatible with package z
of package z

Package z specifies an open PACKAGE_VER_POSSIBLE_INCOMP: Ignore


version range for package x, and Package x version y might be incompatible with
package x is in that open range package z
but not on the edge

Package x requires another SPECMAN_VER_INCOMP: Package x is Warning


Specman version incompatible with Specman version y

Package x specifies an open SPECMAN_VER_POSSIBLE_INCOMP: Ignore


version range for Specman, and Package x might be incompatible with Specman
Specman is in that open range version y
but not on the edge

e Reuse Methodology 2-17


Verification Packages
Using the Package Compatibility Analyzer

All notifications include the required version and the path to the PACKAGE_README.txt file that
specifies the compatibility requirement. In Specview, the path to the PACKAGE_README.txt file is
also a hyperlink.

Notification Examples
*** Warning: WARN_SPECMAN_VER_INCOMP: Package ex_soc is incompatible with
Specman version 4.2
Requirement: Specman 4.3
See: file:/erm_lib/ex_soc/PACKAGE_README.txt

*** Warning: WARN_PACKAGE_VER_INCOMP: Package ex_atm version 1.0 is


incompatible with package ex_soc
Requirement: ex_atm 0.4
See: file:/erm_lib/ex_soc/PACKAGE_README.txt

*** Warning: WARN_PACKAGE_VER_POSSIBLE_INCOMP: Package ex_c_bus version 1.0


might be incompatible with package ex_soc
Requirement: ex_c_bus .. 1.5
See: file:/erm_lib/ex_soc/PACKAGE_README.txt

Customizing Severity of Notifications


The Package Compatibility Analyzer can be customized to change the severity of the checks.

To change the severity of the checks:


• Use the set notify -severity command.
For example, you can change all of the Specman compatibility messages to ERROR as follows:
set notify -severity = ERROR WARN_SPECMAN_VER*

Generating a List of Incompatibilities for Loaded Packages


The Package Compatibility Analyzer can print out a list of all incompatibilities for loaded packages.

To generate a list incompatibilities for loaded packages:


• Use the show incomp[atibility] command.
show incomp
This results in output like the following:
Incompatibilities for loaded packages:

1. Package evc_util might be incompatible with Specman version

2-18 e Reuse Methodology


Verification Packages
PACKAGE_README.txt File

4.1b3
Requirement: Specman 4.0 ..
See: file:/erm_lib/evc_util/PACKAGE_README.txt

2. Package ex_soc is incompatible with Specman version 4.1b3


Requirement: Specman 4.3
See: file:/erm_lib/ex_soc/PACKAGE_README.txt

2.6 PACKAGE_README.txt File


This file is mandatory. The format of the PACKAGE_README.txt file should satisfy the following
requirements:

• Standardization of information (version, for example)


• Easy to read
• Easy to search
• Easy to process automatically (see “User-Visible Methods in any_env” on page 2-24)

2.6.1 PACKAGE_README.txt Location


The PACKAGE_README.txt file should be located in the package directory. For example:
vr_ahb_evc/PACKAGE_README.txt

2.6.2 PACKAGE_README.txt Headers

Header Format
The format of headers should be
* header-name: text
Or:
* header-name:
.... Lines of texts extending until the next header ...

All header lines start with an asterisk (*). The header name is always followed by a colon (:).

A header line can contain text in addition to the header or it can contain only the header.

e Reuse Methodology 2-19


Verification Packages
PACKAGE_README.txt Headers

Headers are considered to be case- and blank-insensitive, but we recommend following the examples in
these respects.

Mandatory Headers
The following headers just appear in the PACKAGE_README.txt file:

• Title
• Name
• Version
If any of these headers are missing or empty or if the value of Name does not match the package
directory name, the PACKAGE_README.txt is considered invalid. (See “Checking Package Legality”
on page 2-22.)

Standard Headers
The PACKAGE_README.txt file should contain standard headers. Verisity predefines the following
headers:

• Title
• Name
• Version
• Category
• Modified
• Support
• Comments to
• Documentation
• Description
• Installation
• Release notes
• To demo
• Requires

Other headers can be added as needed.

PACKAGE_README.txt Examples
Following are sample PACKAGE_README.txt files.

Note Comments starting with “--” are metacomments. They should not appear in the file.

• PACKAGE_README.txt for an eVC

2-20 e Reuse Methodology


Verification Packages
PACKAGE_README.txt Headers

---------- Start of PACKAGE_README.txt file --------------


* Title: Verisity AHB eVC
-- Should be on one line.
-- Another example: An IEEE 335 foo-transfer protocol eVC

* Name: vr_ahb_evc
-- Must be the same as the package name

* Version: 3.3
-- Can also be e.g.: 0.1 (Experimental Version)

* Modified: 14-Jul-2001
-- Please use dates in exactly that format

* Category: eVC
-- Can be eVC, shareware, or utility for now

* Support: evc_support@verisity.com
-- Where to send requests for support, questions, etc..

* Documentation: docs/user_man.pdf
-- File name containing the documentation
-- Note: File names should be specified relative to the
-- package dir

* Release notes: docs/rel_notes.txt

* Description:

The Verisity AHB eVC is ...


....
....

* Directory structure:

This package contains the following directories:

e/ - All e sources
...
...
...

* Installation:

To install it:
....1.

e Reuse Methodology 2-21


Verification Packages
Checking Package Legality

....2.

* To demo: run demo.sh


-- A description of how to run a demo from scratch

---------- End of PACKAGE_README.txt file ----

• PACKAGE_README.txt for simple shareware


In this example there is no separate documentation directory. In fact, the whole shareware consists
of a directory that contains this PACKAGE_README.txt file and a sub-directory called e/ with a
single .e file.
------------ Start of PACKAGE_README.txt file ---
* Title: A utility to print your unit hierarchy

* Name: vr_hier_unit

* Version: 0.1 (very experimental)

* Modified: 13-Nov-2001

* Category: Shareware

* Comments to: John@acme.com (John Doe)


-- Note that in this case John used "Comments to", since he is
-- unwilling to claim there is real "support" for this package

* Description:

To see what it does:

1. Load your design.

2. Load vr_hier_unit/e/vr_hier_unit_top.

3. Type "show unit hier".

You should see a nicely-printed hierarchy of your current


units.
--------------- End of PACKAGE_README.txt file ----

2.7 Checking Package Legality


At the end of generate_test(), Specman goes through all file names, looking for all files matching:
/any_lib/any_package/e/any_package_top.e

2-22 e Reuse Methodology


Verification Packages
any_env Unit

If any directory contains a file called PACKAGE_README.txt, it is assumed to be a package directory


and the PACKAGE_README.txt file is checked for validity. If it does not contain valid Title, Name,
and Version headers, this is regarded as an error. (See also “PACKAGE_README.txt Headers” on page
2-19.)

Finally, each any_env in the unit tree is matched with the package in which it is defined. If it is not
defined in any package, this is regarded as an error.

Note The defining package of an any_env unit is used in some of the env's methods. See “any_env Unit”
on page 2-23.

2.8 any_env Unit


The any_env unit, defined in evc_util, should be the root unit for any separately packaged verification
component (for example, an eVC or a shareware verification component).

For example:
unit vr_xbus_env like any_env {
...
};

Thus, any_env acts like a super-unit, encapsulating the whole verification component.

Each specific any_env definition (such as the vr_xbus_env above) should occur inside some package,
and that package is automatically associated with that env.

This section includes:

• “any_env Unit Example” on page 2-23


• “User-Visible Methods in any_env” on page 2-24

2.8.1 any_env Unit Example


Following is one way in which this association is used.

At the end of generation of sys, Specman shows a banner for each any_env instance. By default, this
shows the title and version number of the corresponding package, but this can be changed by the eVC
writer (see below).

Thus, the log file contains information about which eVCs (and shareware components), and specifically
which versions, participated in the run.

e Reuse Methodology 2-23


Verification Packages
User-Visible Methods in any_env

Sample Output of any_env Banners


Following is an example of the banners written out at the end of the gen command after loading the
vr_xsoc environment.
Specman tc> gen Doing setup ... Generating the test using seed 1...

-------------- vr_xsoc_env_u-@0
The Verisity XSoc Verification Environment - version 0.2 (experimental)
(c) Verisity 2002 XSoc
instance : ENV
-------------- E path: sys.xsoc_env

-------------- vr_xbus_env_u-@1
The Verisity XBus eVC - version 0.5 (experimental)
(c) Verisity 2001
Bus : XBUS
1 eVC-supplied masters
0 shadowed DUT masters
0 eVC-supplied slaves
1 shadowed DUT slaves
eVC-supplied arbiter
-------------- E path: sys.xsoc_env.xbus_evc

-------------- vr_xserial_env_u-@2
The Verisity XSerial eVC - version 0.5 (experimental)
(c) Verisity 2002
eVC instance : XSERIAL_A_RX
has RX ACTIVE agent
-------------- E path: sys.xsoc_env.xserial_A_evc

-------------- vr_xserial_env_u-@3
The Verisity XSerial eVC - version 0.5 (experimental)
(c) Verisity 2002 eVC instance : XSERIAL_B_RX
has RX ACTIVE agent
-------------- E path: sys.xsoc_env.xserial_B_evc

2.8.2 User-Visible Methods in any_env


The any_env unit has some important methods, all of which have a default definition that can be
modified. For example, the show_banner() method shows a banner regarding the current env instance.
By default, it shows the title and version of the corresponding package, but you can extend it (for
example, using is also) to show whatever you want. The same show_banner() method is called in the
show packages command.

Following are definitions of all user-visible methods.

2-24 e Reuse Methodology


Verification Packages
User-Visible Methods in any_env

<'
unit any_env {

get_file(name: string): string is empty;


// Return the full file name (starting with "/") of that file,
// looking for it under the package directory (as it exists now).
// For an empty string - return the package directory.
// If it does not exist, issue an error.
// Computed from definition file of package. User should not override.

get_name(): string is empty;


// Return the name of the package (e.g. "vr_xbus", not the name
// of this unit, which is e.g. "vr_xbus_env").
// Computed from definition file of package. User should not override.

get_title(): string is empty;


// Return the title of the package.
// By default, returns PACKAGE_README.txt title. User can modify it.

get_version(): string is empty;


// Return the version of that package, as a string
// By default, returns PACKAGE_README.txt version. User can modify it.

show_banner() is empty;
// Print the banner for this instance of the env.
// By default, shows a single line, with get_title() and get_version().
// User can modify it, adding e.g. copyright notice and a short
//description
// of the configuration of this instance. We suggest indenting all the
// extra information by four spaces.

show_status() is empty;
// Print the current status of this instance of the env.
// By default, empty. To be filled by the user.

add_wave_info() is empty;
// Add waveform info for that package.
// By default, empty. To be filled by the user.
};
'>

There can be several related children of any_env in one package. If they need different titles, that could
be one situation where you would want to override the default implementation, in this case, of
get_title().

e Reuse Methodology 2-25


Verification Packages
show packages Command

2.9 show packages Command

Syntax
show packages [-full] [wildcard-name]

This shows all currently loaded packages. If the current simulation environment contains instances of
any_env defined in the package, then the banner of those instances is also shown.

If -full is specified, the status of each instance is also shown (as specified by any_env.show_status()).

If wildcard-name is specified, only packages with package name matching the wildcard name are
shown. For example, you could show all shareware packages as follows:
show packages shr_*

show packages -on_disk [-full] [wildcard-name]

This shows all the current packages in libraries along the $SPECMAN_PATH.

If -full is specified, you get information about illegal packages along the path.

If wildcard-name is specified, only packages with package name matching the wildcard name are
shown.

Note The experimental vt_util package (still beta) also gives a GUI way to see loaded packages and
packages on disk. (For more information, see “The vt_util Windows” in The vt_util Package located in
$SPECMAN_HOME/erm_lib/vt_util/docs/vt_util.pdf.)

This section includes:

• “Checking Package Legality” on page 2-22


• “Example of show packages Output” on page 2-26

2.9.1 Example of show packages Output


Following is the output resulting from the show packages command after loading vr_xsoc and issuing
the gen command. Note the any_env banners.
Specman tc> show packages

----- Loaded packages:

0. Package: evc_util
Version: 0.3
Comments to: support@verisity.com

2-26 e Reuse Methodology


Verification Packages
Example of show packages Output

Title: The common eVC utilities, imported by all packages


See: file:/cad/evc_lib/evc_util/PACKAGE_README.txt

1. Package: vr_xserial
Version: 0.5 (experimental)
Comments to: support@verisity.com
Title: The Verisity XSerial eVC
See: file:/cad/evc_lib/vr_xserial/PACKAGE_README.txt

-------------- vr_xserial_env_u-@2
The Verisity XSerial eVC - version 0.5 (experimental)
(c) Verisity 2002
eVC instance : XSERIAL_A_RX
has RX ACTIVE agent
-------------- E path: sys.xsoc_env.xserial_A_evc

-------------- vr_xserial_env_u-@3
The Verisity XSerial eVC - version 0.5 (experimental)
(c) Verisity 2002
eVC instance : XSERIAL_B_RX
has RX ACTIVE agent
-------------- E path: sys.xsoc_env.xserial_B_evc

2. Package: shr_ram
Version: 0.1
Comments to: support@verisity.com
Title: Sparse RAM Model (shareware)
See: file:/cad/evc_lib/shr_ram/PACKAGE_README.txt

3. Package: vr_xbus
Version: 0.5 (experimental)
Comments to: support@verisity.com
Title: The Verisity XBus eVC
See: file:/cad/evc_lib/vr_xbus/PACKAGE_README.txt

-------------- vr_xbus_env_u-@1
The Verisity XBus eVC - version 0.5 (experimental)
(c) Verisity 2001
Bus : XBUS
1 eVC-supplied masters
0 shadowed DUT masters
0 eVC-supplied slaves
1 shadowed DUT slaves
eVC-supplied arbiter
-------------- E path: sys.xsoc_env.xbus_evc

4. Package: vr_xsoc

e Reuse Methodology 2-27


Verification Packages
Recommend nations

Version: 0.2 (experimental)


Comments to: support@verisity.com
Title: The Verisity XSoc Verification Environment
See: file:/cad/evc_lib/vr_xsoc/PACKAGE_README.txt

-------------- vr_xsoc_env_u-@0
The Verisity XSoc Verification Environment - version 0.2 (experimental)
(c) Verisity 2002
XSoc instance : ENV
-------------- E path: sys.xsoc_env

2.10 Recommend nations


This section describes recommendations regarding packages:

• “Shipping and Receiving Whole Libraries” on page 2-28


• “Instantiating Non-Env Utilities” on page 2-29
• “Adding Suffixes to Types” on page 2-29
• “Connecting any_env to Package” on page 2-29

2.10.1 Shipping and Receiving Whole Libraries


Sometimes, it is more practical to ship whole libraries of packages rather than each package separately.
For example, this might be the case when multiple related packages were all updated, and working with
one of the new packages requires the latest version of the other packages too.

eRM allows for shipping whole libraries. Nevertheless, we do have a few recommendations:

• When shipping a library:


• The library should be tarred and gzipped.
• The name of the tar file should indicate the version or date of release.
• The LIBRARY_README.txt file should identify the details of the library release.
• When receiving a library:
• When receiving whole libraries from a library developer/vendor, the library would typically
replace the previous library.
• In maintaining libraries received from external sources, it is best not to add foreign packages to
the same library. For example, Verisity ships the erm_lib, and you should not add your own
packages there.

2-28 e Reuse Methodology


Verification Packages
Instantiating Non-Env Utilities

• This is not to be confused with the situation of receiving packages from multiple vendors, in
which case multiple packages can be placed in a common library. For examples, you might buy
eVCs from multiple vendors and place them all in one library called “commercial_evcs”.

2.10.2 Instantiating Non-Env Utilities


We suggest that non-env shareware utilities be instantiated under the sn_util struct under global.

For example, suppose you define a new shareware package that draws graphs (call it shr_graph), with a
main struct called shr_graph. You can instantiate it under sn_util with the following code in
shr_graph_top.e:
extend sn_util {
shr_graph: shr_graph;
init() is also {shr_graph = new};
};

You can then access fields in the shr_graph struct as:


util.shr_graph.foo();

2.10.3 Adding Suffixes to Types


This is not directly related to packages, but we recommend having all unit names end with _u, all structs
with _s, all scalar types with _t, and so on.

2.10.4 Connecting any_env to Package


If a specific env (child of any_env) is not defined in a package, this results in a runtime error after
generation.

e Reuse Methodology 2-29


Verification Packages
Connecting any_env to Package

2-30 e Reuse Methodology


3 eVC File Organization
This chapter contains the following sections:

• “eVC Directory Structure” on page 3-1


• “Partitioning eVC Source into Files” on page 3-3
• “File Naming Guidelines” on page 3-4
• “Instantiating Entities” on page 3-5
• “Importing Files” on page 3-7
• “File Clusters” on page 3-7
• “Files: Cyclic Dependencies” on page 3-8

3.1 eVC Directory Structure


The distribution for an eVC should be organized logically with eVC source files separated from
documentation, demonstration code, and so on.

As a minimum, we recommend placing the following three subdirectories at the top level of the eVC
directory.

evc/e/ This directory should contain all source code for the eVC.
evc/examples/ This directory should contain examples of how to use the eVC.
evc/docs/ This directory should contain all documentation for the eVC.

Other subdirectories may be appropriate in some cases. For example, with an eVC that is designed to
facilitate integration of a design block, a subdirectory named evc/rtl/ might be used to contain the RTL
code (in VHDL or Verilog) for the design block.

e Reuse Methodology 3-1


eVC File Organization
evc/e/

This section includes:

• “evc/e/” on page 3-2


• “evc/examples/” on page 3-3
• “evc/docs/” on page 3-3

3.1.1 evc/e/
All eVC source files should be placed under evc/e/. As a minimum, an eVC must have a file named
evc/e/evc_top.e. This file should import all other files required for correct loading of the eVC. As such,
users of an eVC can load it by placing the following line at an appropriate point in their code.
import evc/e/evc_top;

In exceptional circumstances, it might be appropriate for an eVC to be loaded in a number of different


subsections or different configurations. In such a case, multiple top-level files can be provided. For
example:

evc/e/evc_top.e

evc/e/evc_configuration_a_top.e

evc/e/evc_configuration_b_top.e

or:

evc/e/evc_top.e

evc/e/evc_master_top.e

evc/e/evc_slave_top.e

Note There must still be a file named evc/e/evc_top.e to satisfy the requirements for packaging.

Source Subdirectories
For larger eVCs, we recommend that source files be split into subdirectories under the evc/e/ directory.
Each subdirectory should contain an appropriately named _top.e file that is imported by the
evc/e/evc_top.e.

Subdirectory names should be short and should describe an area of the eVC (usually a subcomponent or
aspect of the eVC). For example (showing the top level files for each subdirectory):

evc/e/master/evc_master_top.e

evc/e/interrupts/evc_interrupts_top.e

3-2 e Reuse Methodology


eVC File Organization
evc/examples/

evc/e/tcp/evc_tcp_top.e

evc/e/coverage/evc_coverage_top.e

Notes
• We recommended that the /evc/e subdirectory names do not include the evc_ prefix.
• All files in an eVC release must have unique names. If there are multiple references to the same file,
the file is loaded only once. If there is an attempt to load a file with the same name but different
location as an already loaded file, Specman issues an error message.

3.1.2 evc/examples/
Sample config and test files should be placed in evc/examples/. As a minimum, this should include:

• A template configuration file that users can use as a starting point for building an eVC configuration
• A fully working demonstration/example of the use of the eVC
Users should be able to run the full demonstration (including creating/compiling simulator libraries, and
so on) by sourcing a script named demo.sh. This script should be placed at the top level of the eVC
directory structure (for example, evc/demo.sh).

3.1.3 evc/docs/
All documentation for the eVC should be placed under evc/docs/. This normally includes both release
notes and a user guide. Where documents change according to the version of the eVC, we recommend
indicating the current version as part of the filename. For example:

evc/docs/evc_release_notes_version_1_2.pdf

evc/docs/evc_user_guide_version_1_2.pdf

Where a large number of documents are provided, these should be placed in an appropriate subdirectory
structure under evc/docs/.

Although a number of different documentation formats are appropriate for eVC documentation, we
recommend providing documentation in TXT or PDF formats as these are likely to be readable by the
largest number of users.

3.2 Partitioning eVC Source into Files


When possible, eVC source files should be kept short and split logically. Files should be split by

• Topic/entity (for example, env, master, arbiter, burst)

e Reuse Methodology 3-3


eVC File Organization
File Naming Guidelines

• By the various appropriate aspects. For example:


• Feature aspects: checker, coverage, sequences, APIs, and so on.
• Protocol aspects: USB power, bus resets, and so on.
• According to whether their content is part of the public interface of the eVC (such files should have
the suffix “_h.e”) or part of the private body of the eVC. As a general rule, this public/private split
should follow any split between encrypted and unencrypted code.

3.3 File Naming Guidelines


Table 3-1 Standard Naming (for plug-and-play and Readability)

Guideline Details

Prefix for ALL eVC source files evc_

The eVC top file always located at evc/e/evc_top.e

Standard names for feature files An appropriate name of the feature, for
example, checker, cover, monitor, sequence

Natural domain names for entities Examples are master, slave, burst

Uniform order/prefix/suffix of names (agent first, evc_master.e, evc_checker.e


feature last) evc_master_checker.e, evc_slave_checker.e
evc_master_monitor.e, evc_slave_monitor.e

Table 3-2 Files Owned by eVC Developer (users should not modify)

File Name Description

evc_types.e Global constants and types belonging to the eVC

evc_data_item.e Definition of the data item struct evc_data_item

evc_agent_h.e Header file: definition of an agent unit (optional)

evc_agent.e Implementation of an agent unit

evc_env.e Definition of the top-level unit evc_env

evc_monitor.e Definition of central monitor unit, when relevant (for example, buses)

evc_agent_monitor.e Definition of agent monitor unit, when relevant (for example, serial i/f)

3-4 e Reuse Methodology


eVC File Organization
Instantiating Entities

Table 3-2 Files Owned by eVC Developer (users should not modify) (continued)

File Name Description

evc_agent_sequence.e Predefined sequences / API methods

evc_checker.e Protocol and data checks. Can be divided into agent/topic files

evc_agent_checker.e Specific checks for each agent

evc_cover.e Coverage definitions

evc_agent_cover.e Coverage definitions

evc_wave.e Definitions of wave commands for the eVC

evc_top.e • Imports all files


• Instantiates eVC entities
• Passed to sn_compile

Table 3-3 Files Owned by Users (supplied in evc/examples directory)

File Name Description

evc_config_template.e • Shows all eVC config fields


(evc_config_*.e) • Shows a sample configuration (may have several such files)
• Instantiates the eVC env in the user’s environment.
• Imports both evc_top.e and evc_setup_example.e
• Imported by tests—serves as basis to import the whole eVC
Note This template file MUST be provided in all eVCs and should be
placed in the evc/examples/ subdirectory.

evc_defines_template.e Environment constants that use define (if needed)


(evc_defines_*.e)

3.4 Instantiating Entities


Table 3-4 Examples of File Organization

vr_xserial vr_xbus

vr_xserial_types; vr_xbus_types;

vr_xserial_env; vr_xbus_env;

e Reuse Methodology 3-5


eVC File Organization
Instantiating Entities

Table 3-4 Examples of File Organization (continued)

vr_xserial vr_xbus

vr_xserial_agent; vr_xbus_agent;

vr_xserial_bfm; vr_xbus_bfm;

vr_xserial_bfm_tx; vr_xbus_bfm_arbiter;

vr_xserial_bfm_rx; vr_xbus_bfm_master;

vr_xserial_monitor; vr_xbus_bfm_slave;

vr_xbus_monitor;

vr_xserial_frame; vr_xbus_trans;

vr_xserial_coverage; vr_xbus_protocol_checker

vr_xserial_log; vr_xbus_log;

vr_xserial_sequence_tx; vr_xbus_coverage;

vr_xserial_sequence_rx; vr_xbus_master_sequence;

vr_xserial_protocol_checker vr_xbus_slave_sequence;

vr_xserial_top; vr_xbus_top;

vr_xserial_config_template vr_xbus_config_template

test_1 test_1

An eVC should never instantiate anything under sys. This is important because an eVC may later be
instantiated under a larger eVC. Instead, all subcomponents of the eVC should be instantiated under a
unit named evc_env_u. The user’s evc_config.e file will then instantiate evc_env_u at an appropriate
point or points in the user’s verification environment.

To promote reuse of code within an eVC, structs and units should not be instantiated in the file that
declares them. For example, if the file evc_master.e declares a unit evc_master_u, then no instance of
this unit will be created in this file. The instance of the unit evc_master_u might be created in the file
evc_env.e.

3-6 e Reuse Methodology


eVC File Organization
Importing Files

3.5 Importing Files


The file evc/e/evc_top.e should import all other eVC source files. This can be done either explicitly by
importing all source files directly, or implicitly by importing lower-level _top.e files that in turn import
other source files. Typically, the lower-level _top.e files and the files they import are placed in a
subdirectory under evc/e/ (see “Source Subdirectories” on page 3-2).

Additionally, any file can optionally import other files on which it depends. This can be useful for
documenting dependencies and solving cyclic dependencies.

All imports in eVC code are performed using either local or package-relative filenames:

• Local filenames refer to files in the same directory as the importing file or in a subdirectory below
it. For example:
import evc_another_file.e; // File in same directory
import ./sub_dir/evc_another_file.e; // File in subdirectory
Note Imports within a package should be local (as much as possible). This is the safest way to
make sure that the package will be loaded from one location, even if you maintain multiple versions
of the package.

Note “../” should never be used as part of an import statement, because this can lead to undesired
results if there are symbolic links in your directory path. For example:
import ../evc_another_file.e; // This kind of path specification
// should not be used

• eVC-relative filenames refer to files relative to the top-level of the eVC. For example:
import evc/e/evc_top.e; // Import the top level file of the eVC
import evc/e/evc_env.e; // Import file that declares env unit
Note Imports of other eVCs or utilities are always performed using eVC-relative filenames. This
is to make sure that the package is found, regardless of the locations of the importing file and the
imported package (SPECMAN_PATH takes care of it all). For example:
import evc_util/e/evc_util_top.e; // Import the evc_util utility

3.6 File Clusters


When possible, each unit within a design should be treated as a separate object that does not depend on
any objects higher in the unit hierarchy of the eVC. However, in some cases, this is not possible or not
practical. For example, in a bus-based eVC, the bus agents might need to know about the env unit under
which they are instantiated. In such cases, a stronger dependency between certain files in the eVC is
required.

e Reuse Methodology 3-7


eVC File Organization
Files: Cyclic Dependencies

In such cases, files may be organized into clusters of related files. A cluster should be loaded at one time,
allowing tighter dependencies between the files that make up the cluster. Within a cluster, some of the
guidelines on file organization can be relaxed (out of practicality). For example:

• Units can instantiate themselves in other units declared within the cluster where the relationships
between the units in the cluster is fixed by the eVC.
• Files can depend cyclically upon each other.
Several clusters can exist within an eVC, and the eVC as a whole can be considered as a cluster. Where
a file cluster is used, we recommend placing it in a subdirectory with a _top.e file. The evc_top.e file can
then import the file cluster by importing its _top.e file.

3.7 Files: Cyclic Dependencies


In some cases, you might want to split code into two or more files, but this results in a cyclic dependency
between the files. For example, the file evc_env.e declares a unit evc_env_u and instantiates the unit
evc_agent_u under it. The file evc_agent.e declares the unit evc_agent_u, which contains a backpointer
to the unit evc_env.e. In this case, each file requires that the other already be loaded.

This situation can be solved using the cyclic import feature in Specman. If evc_env.e imports
evc_agent.e, and evc_agent.e imports evc_env.e, then Specman detects the cyclic dependency between
them and loads both files together as if they were one file. These files are considered part of the same file
cluster. We recommend that the appropriate _top.e file imports both files.

Notes
• Mutually extending structs/units in cyclic files might introduce problems.
• We recommend keeping the use of cyclic imports to a minimum. When there are many cyclic
dependencies, it leads to large clusters that can be difficult to manage.

Example
user_config.e
<'
import top;
extend sys {
env: env_u is instance;
};
'>

env.e
<'
import agent;
unit env_u like any_env {

3-8 e Reuse Methodology


eVC File Organization
An Alternative Approach to Cyclic Dependencies

agent: agent_u is instance;


keep agent.env_bp == me;
};
'>

agent.e
<'
import env;
unit agent_u {
env_bp: env_u;
};
'>

top.e
<'
import env;
import agent;
'>

See Also
• “An Alternative Approach to Cyclic Dependencies” on page 3-9

3.7.1 An Alternative Approach to Cyclic Dependencies


In some cases, the use of cyclic imports can make the code difficult to maintain. In such cases, we
suggest using a single file to declare all affected units, but without adding any content. The individual
files can then extend each unit to add the content and can refer to the previously declared unit types
without cyclic dependencies.

A similar approach can be used to solve cyclic method dependencies. Using this approach, you declare
the methods as empty in an initial file, then extend the methods to add the method bodies in subsequent
files.

Note This approach provides a weaker encapsulation of objects.

Example
units.e
<'
unit env_u like any_env {};
unit agent_u {};
'>

agent.e

e Reuse Methodology 3-9


eVC File Organization
An Alternative Approach to Cyclic Dependencies

<'
import units;
extend agent_u {
env_bp: env_u;
};
'>

env.e
<'
import units;
import agent;
extend env_u {
agent: agent_u is instance;
keep agent.env_bp == me;
};
'>

top.e
<'
import units;
import agent;
import env;
'>

3-10 e Reuse Methodology


4 Typical eVC Architecture
This chapter explains how typical eVCs should be constructed.

Because each eVC relates to different protocols, architectures, and designs, one eVC can vary quite
significantly from another. Even so, there is commonality in the design of various eVCs. In this chapter,
we discuss the commonality and some of the main differences between typical eVCs. The examples we
look at relate to communication protocols, such as a serial interface or an on-chip bus. Later, we will see
that an eVC for an SoC is constructed according to similar guidelines.

The end of this chapter lists extensive terminology definitions and a complete legend for the architecture
diagrams presented in this book.

This chapter includes the following sections:

• “Basic eVC Architecture” on page 4-1


• “A Look at Agents” on page 4-6
• “A More Complex eVC Example” on page 4-12
• “Combining eVCs” on page 4-14
• “Layering eVCs” on page 4-15
• “Modeling FAQs” on page 4-22
• “Terminology” on page 4-23

4.1 Basic eVC Architecture


This section includes:

• “DUT and eVC” on page 4-2


• “BFMs and Monitors” on page 4-5

e Reuse Methodology 4-1


Typical eVC Architecture
DUT and eVC

• “Clocks and Events” on page 4-6


• “DUT Signals” on page 4-6

4.1.1 DUT and eVC


Figure 4-1 below shows a sample DUT that we use to demonstrate eVCs.

Figure 4-1 Example DUT

DUT
Bus Logic Serial Logic

This DUT has two external interfaces: a bus interface and a serial interface. Because each of these
interfaces can interact externally, we can attach an eVC to exercise and interact with each of them.

We start by looking at the serial interface. This interface is composed of a receive port and a transmit
port. The eVC attached to this interface is the vr_xserial eVC. The dual-agent implementation for the
XSerial eVC is shown in Figure 4-2 below. (The actual implementation of the XSerial eVC is slightly
different. It is shown in Figure 4-3 on page 4-4.)

Figure 4-2 XSerial eVC—Dual-Agent Implementation

xserial_env
RX Agent TX Agent
Config:
... Config Config

Signal Map Signal Map

Sequence Sequence
Driver Driver

seq seq

Mon BFM Mon BFM

DUT
Bus Logic Serial Logic

4-2 e Reuse Methodology


Typical eVC Architecture
DUT and eVC

The XSerial eVC is encapsulated in the rectangle marked “xserial_env”. This rectangle represents an
instance of a unit of type vr_xserial_env_u (which inherits from any_env, as described in “any_env Unit”
on page 2-23). For each port of the interface, the eVC implements an agent. These agents can emulate
the behavior of a legal device, and they have standard construction and functionality. Each env also has
a group of fields, marked in Figure 4-2 as Config. This allows for configuration of the env’s attributes and
behavior.

The agents are units instantiated within the env.

In this representation of the eVC, there are two types of agent:

RX agent A receive agent that can collect data from the DUT’s transmit port

TX agent A transmit agent that can send data to the DUT’s receive port

These agents are constructed in a standard manner. They have the following components:

Config A group of fields that allow configuration of the agent’s attributes and
behavior

Signals A group of unit members that represent the HW signals that the agent must
access as it interacts with the DUT. Currently, the signals are implemented
as string fields, all prefixed with “sig_”.

Sequence Driver A unit instance that serves as a coordinator for running user-defined test
scenarios (implemented as sequences). The sequence drivers are explained
in detail in Chapter 5 “Sequences: Constructing Test Scenarios”.

BFM Bus Functional Model—a unit instance that interacts with the DUT and both
drives and samples the DUT signals.

Monitor A unit instance that passively monitors (samples) the DUT signals and
supplies interpretation of the monitored activity to the other components of
the agent. Monitors can emit events when they notice interesting things
happening in the DUT or on the DUT interface. They can also check for
correct behavior or collect coverage.

In Figure 4-2, notice that the BFMs have bidirectional arrows to the DUT. This signifies the fact that they
can both drive and sample DUT signals. Monitors have unidirectional arrows pointing from the DUT to
them. This signifies that they can only sample data from the DUT. Monitors cannot drive DUT signals.

The actual implementation of the XSerial eVC is slightly different than the architecture shown in Figure
4-2. Instead of a dual-agent architecture, a single-agent architecture was chosen (see Figure 4-3 below).

e Reuse Methodology 4-3


Typical eVC Architecture
DUT and eVC

Figure 4-3 XSerial eVC—Single-Agent Implementation

xserial_env
TX_AND_RX Agent
Config:
... Config

Signal Map

Sequence
Driver
seq

RX TX TX
Mon Mon BFM

DUT
Bus Logic Serial Logic

Both the dual-agent and the single-agent architectures are valid implementations. Depending on the
specifics of the protocol the eVC deals with, you might prefer one over the other.

In the XSerial protocol, the RX direction is completely passive and involves no driving of signals. Thus
there is no need to have a BFM and a sequence driver in the RX agent. However, the TX agent behavior
also depends on flow control frames received by the RX agent. This means that the RX agent must
communicate frequently with the TX agent to tell it when it has received such frames.

In the XSerial protocol, the XSerial eVC could have two agents—an RX agent and a TX agent—where
the RX agent is significantly more simple than the TX agent. If the flow control mechanism involves a
high level of interaction between the two directions, implement a single-agent eVC to model the flow
control mechanism efficiently. The single agent covers both the TX and RX directions. The single agent
contains all of the monitors, BFMs, and sequence drivers required for both directions.

4.1.1.1 Diagram Language


What we have described up to now is the typical, generic parts of an eVC environment. Before looking
deeper into the construction of an agent or examining other variants of eVC architecture, let us
understand the language we have been using in these architecture diagrams.

Figure 4-4 gives a brief legend for architecture diagrams.

4-4 e Reuse Methodology


Typical eVC Architecture
BFMs and Monitors

Figure 4-4 Brief Legend for Architecture Diagrams

Enclosing unit Topic:


Unit unit Unit instantiation Field grouping field 1
Instantiated unit ...

Struct struct
Enclosing unit
Subtype DUT access
Data item Subtype
DUT
Struct/unit pointer struct unit

Most importantly, notice the difference between structs and units, and the difference between unit
instantiation as opposed to pointers between structs and units. The fact that unit instantiation is depicted
by enclosing one unit rectangle within another serves to express the important relations between the
main entities in an eVC architecture.

Notice also that in Figure 4-2 the DUT was drawn in gray at the bottom of the picture. This convention
is maintained throughout the rest of this manual.

A more complete legend is supplied at the end of this chapter in the figure “Full Legend for Architecture
Diagrams” on page 4-26. The more complete legend will be helpful when examining the diagrams in
Chapter 5 “Sequences: Constructing Test Scenarios”.

4.1.2 BFMs and Monitors


Monitors must be completely passive. The BFM does all of the activity of driving transactions. The
BFM can make use of the monitor or duplicate some of the monitor's logic. (Both are legitimate;
developers must decide which fits their needs.)

Generally, the monitor handles most passive activity, and the BFM handles all active interactions with
the DUT. For example, the monitor might collect transactions and then emit an event for each
transaction received. Upon this event, the BFM could be responsible for sending an acknowledgment
back to the DUT.

We recommend using the monitor rather than the BFM to collect transactions that come from the DUT.
This can happen in the following ways:

• In many protocols, each agent in the eVC has both a BFM and a monitor. (See the XBus golden eVC
for an example.)
• In some protocols, the Receive side might not have any active components, so there is no BFM or
sequence driver at all. In such cases, the Receive monitor can be placed inside a single agent that
combines Receive and Transmit activities. This is especially convenient if the Receive and Transmit
sides interact. (See the XSerial golden eVC for an example.)

e Reuse Methodology 4-5


Typical eVC Architecture
Clocks and Events

4.1.3 Clocks and Events


One decision facing eVC developers is whether to have the clock(s) propagated down to each agent or
to use a central clock in the env that all agents will refer to.

We recommend the following:

• To the extent possible, one centralized clock should be used and it should be located in the env.
(Similarly, any other frequently occurring event should be centralized.) The primary reason for this
is to eliminate unnecessary performance overhead.
• On the other hand, if the protocol defines that agents can have different clocks (for example, different
speeds), then each agent should have its own clock.

Centralized clocks should be implemented by maintaining a backpointer from the agents to the
enclosing env and referring to events in the env as env.clock. This comes at the expense of modularity.
We consider this a reasonable tradeoff, because in most cases the agent and the env can be considered a
unit cluster. This means that the interactions and dependencies between them are close enough to
assume that they will always be used together.

Note Sequence drivers will always have their own clock. This is necessary to simplify the user
interface by allowing a uniform way to extend the sequence body() TCMs without needing to know the
specific clock name.

4.1.4 DUT Signals


Referring to DUT signals should be done using fields of type string. You can assign field names that all
have a “sig_” prefix or create a sig_map unit to encapsulate all signals. Signal fields should be placed in
a natural location, typically either the env unit (if it is a signal used by all agents) or in an agent (for
agent-specific signals).

4.2 A Look at Agents


This section includes:

• “What Are Agents?” on page 4-7


• “Components of Agents” on page 4-8
• “Some Important Guidelines for Agents” on page 4-12

4-6 e Reuse Methodology


Typical eVC Architecture
What Are Agents?

4.2.1 What Are Agents?


Agents are the key to eVC architecture. In most eVCs, agents represent independent devices and have
standard main elements. Some of the fields in the agents are also standard and should appear in all eVCs.
Examples of this standard organization and these standard fields can be seen in the golden eVCs.

Agents are either ACTIVE or PASSIVE. ACTIVE agents are agents that drive DUT signals. PASSIVE
agents never do that, either because they just monitor an interface within the DUT or because, according
to the protocol, no signals need to be driven. In addition to monitoring the activity of a corresponding
DUT agent, PASSIVE agents can also add checks, scoreboards, and coverage on top of what is
predefined in the eVC. Typically, these should be used in verifying the DUT but should not be part of the
active agent.

This is coded by using a predefined type:


erm_active_passive_t: [ACTIVE, PASSIVE]; // Predefined in evc_util

The user must define the active_passive field. For example:


extend vr_atm_agent_u {
active_passive: erm_active_passive_t;
};

In addition to the ACTIVE / PASSIVE attribute, agents are considered proactive if they initiate
transactions, and reactive if they only respond to requests. These attributes are not reflected as fields or
field values in code.

Both ACTIVE and PASSIVE agents have a monitor. The monitor can be instantiated directly in the
agent.

A PASSIVE agent does not have a BFM or a sequence driver. Both are instantiated within the ACTIVE
subclass (or when clause) of the agent. For example:
unit vr_atm_agent_u {
active_passive: erm_active_passive_t ;
monitor: vr_atm_monitor_u is instance;
when ACTIVE vr_atm_agent_u {
bfm: vr_atm_bfm_u is instance;
seq_driver: vr_atm_sequence_driver is instance;
};
};

When an agent cannot drive signals (because the protocol does not allow it), it does not have an
active_passive field (because it is always PASSIVE).

Other standard fields include kind fields that allow specifying subtypes of agents and name/ID fields
that allow identification of each agent (as described in “Instance Names and IDs” on page 9-6).

e Reuse Methodology 4-7


Typical eVC Architecture
Components of Agents

Any agent in an eVC can be used as a PASSIVE agent. PASSIVE agents represent DUT devices that are
only monitored by the eVC. The PASSIVE agent collects information from the DUT and holds that
information as a reference for the verification environment. This enables orderly monitoring of the DUT
agent—collecting information and checking its behavior from a well defined place in the eVC.

4.2.2 Components of Agents


Figure 4-5 Agent Internals

Agent
Config:
active_passive
name ACTIVE
kind == TX

Sequence
Signal Map Driver
Passive seq

Mon
has_coverage
BFM
has_checker

DUT

All agents have a fixed basic architecture with optional additions as required by the specific
environment.

The interface of an agent consists of a configuration unit, a sequence driver, and the signal map
connecting it to the DUT. Agents should be designed to work as independently as possible, not relying
on a specific type of env, because independent agents are more easily adapted to unforeseen needs that
eVC users might have. Therefore, it is important that the agent configuration and signal map are internal
to the agent and are passed to the agent by the enclosing unit.

Note An agent can also have a pointer to its enclosing environment. Through the pointer, the agent can
obtain the configuration parameters. In this case, the agent is dependent on a specific environment and
can only be instantiated in that specific type of environment.

For more detail on the agent components, see:

• “Agent Configuration and Signals” on page 4-9

4-8 e Reuse Methodology


Typical eVC Architecture
Components of Agents

• “Sequence Drivers” on page 4-9


• “Monitor” on page 4-10
• “BFM” on page 4-10
• “Checker” on page 4-11
• “Coverage” on page 4-11

4.2.2.1 Agent Configuration and Signals


The agent configuration specifies an agent’s interface with the rest of the verification environment. It
contains the mode of operation (for example, active_passive, has_checker, has_coverage) and additional
static information needed for the agent’s operation, such as the bus width, endianness, etc. We
recommend encapsulating these parameters in a config struct to present a well-defined interface for the
agent.

Some configuration fields like active_passive are used for subtyping. These fields must reside in the
agent or be propagated from the config struct to the agent. All other fields are defined in the config
struct. This struct can be constrained from the enclosing unit, thus eliminating the need for a parent
pointer and allowing instantiation of the agent in different environments. For the sake of efficiency,
config fields that are used frequently can be copied into a local field.

Signals connecting the eVC agent to the DUT are string type fields. They are defined either in the agent
itself (prefixed by “sig_”) or in a signal map unit within the agent. As the signals are shared by several
components of the agent such as the monitor and the BFM, a signal map unit is recommended to make
sharing of signals more convenient.

4.2.2.2 Sequence Drivers


Sequences are the test writer’s interface to control the verification process. All test-specific control,
including reset and error injection, should be available through sequences.

The sequence driver is a unit instantiated in the active agent. By default, it is connected to the BFM in
pull mode. (Push mode is not recommended.) Items generated in the sequence driver are sent to the
BFM whenever an item is available and the BFM is ready to accept a new item. At any given time, the
BFM and monitor provide the current DUT state to the sequence driver for generating sequence items.

The sequence driver must support both standalone operation (generation of items independent of
higher-level protocols) and layering of higher-level protocols (generation of items based on higher-level
protocols).

e Reuse Methodology 4-9


Typical eVC Architecture
Components of Agents

4.2.2.3 Monitor
The monitor is responsible for extracting signal information from the DUT and translating it into
meaningful events and status information. This information is available to other components of the
agent and to the test writer. The monitor should never rely on information collected by other components
such as the BFM.

The monitor is a unit that is always instantiated (regardless of subtypes). Its functionality should be
limited to the basic monitoring that is always required. Additional high-level functionality that might be
required should be implemented separately on top of the monitor. This includes protocol checkers,
scoreboards, and coverage, used typically, but not only, in the passive agent.

The events recognized by the monitor depend on the actual protocol. Typically, for the basic data item
the monitor provides an item_started and an item_ended event (for example, packet_started and
packet_ended). The monitor collects the item data from the signals and creates a current_item that has
the complete item data, ready to be used when the item_ended event occurs. In addition to the raw data,
the monitor should collect relevant timing information such as the duration of the transaction.

Monitor Checking and Coverage


Coverage and checkers should be implemented on top of the monitor in subtypes of the monitor such as
has_checker and has_coverage. That minimizes performance overhead if those units are not used. The
has_checker and has_coverage flags should be propagated to the monitor so that the monitor code can be
optimized.

Global Monitor
Some eVCs require a system-level monitor in addition to the agent-level monitors. This is typically used
in broadcast protocols. In point-to-point protocols, agent monitors are usually sufficient.

4.2.2.4 BFM
BFMs do all of the signal driving from agents.

The BFM is a unit instantiated only in ACTIVE agents. Changing an ACTIVE agent to PASSIVE
prevents that agent from driving signals.

No generation is done in the BFM. The BFM receives a data item (from the sequence driver) and
performs all operations required to send the data item to the DUT according to the protocol rules. The
item should contain all necessary information to complete the transaction.

To perform its task correctly, the BFM must know the current state of the DUT. The BFM can sense the
DUT signals directly or use signal information extracted by the monitor.

4-10 e Reuse Methodology


Typical eVC Architecture
Components of Agents

Errors in the BFM


The BFM should never issue a dut_error. Errors such as unexpected BFM state should be caught by
assertions. If possible, a message might be issued while the flow continues.

Protocol errors should be caught and reported by the checker part of the monitor.

4.2.2.5 Checker
Typically, a checker is used to verify a DUT, but it can also be used to verify the correctness of the active
eVC agent.

The checker can be implemented either as a separate unit in the agent or in a has_checker subtype of the
monitor. By default, the has_checker flag should be TRUE in passive mode and FALSE in active mode.

The checker operates based on events and data collected by the monitor. If it is implemented as a
separate unit, it has a pointer to the monitor that is set by the agent when the checker is instantiated.

At a minimum, the checker should check the validity of the basic data item (for example, packet) and the
related timing requirements according to the protocol.

4.2.2.6 Coverage
Typically, coverage is used to verify a DUT. It can also be used to verify the eVC active agent’s
capabilities by covering sequence types.

Coverage can be implemented either as a separate unit in the agent or in a has_coverage subtype of the
monitor. By default, the has_coverage flag is TRUE in passive mode and FALSE in active mode. If an
end user wants to verify the eVC active agent’s capabilities, the has_coverage flag can be set to TRUE.

Coverage operates based on events and data collected by the monitor. If it is implemented as a separate
unit, it has a pointer to the monitor that is set by the agent when the coverage unit is instantiated.

Default eVC Coverage


The default coverage definition of the eVC should be based on events and data collected in the monitor.
The coverage group should be based on a monitor event that indicates the completion of a transaction
(for example, packet_ended).

The coverage definition includes:

• Significant fields of the data item (for example, packet)


• Related temporal data (for example, delay or transmission time)
• Cross-coverage items required for covering the interface specification

e Reuse Methodology 4-11


Typical eVC Architecture
Some Important Guidelines for Agents

• Additional agent fields indicating the mode of operation

4.2.3 Some Important Guidelines for Agents


Important agent guidelines:

• It is very important to separate the BFM from the monitors. When agents are PASSIVE, they should
be able to use their monitors without interfering with the DUT operation.
• There are many possible names for the main entities in the agent, and people tend to choose differently.
To eliminate unnecessary confusion, we propose the following names for these standard entities:

Use Do Not Use

Agent Device

BFM Driver

Monitor Collector

For more details, see “Terminology” on page 4-23.

4.3 A More Complex eVC Example


The first example we looked at was an eVC for a very simple communication protocol, the XSerial
interface. Now we examine a more complex eVC, an eVC for a bus. Figure 4-6 shows the vr_xbus eVC
added to the DUT verification environment.

4-12 e Reuse Methodology


Typical eVC Architecture
A More Complex eVC Example

Figure 4-6 XBus eVC

xbus_env xserial_env
Config: MASTER SLAVE ARBITER Config: RX Agent TX Agent
name Agent Agent Agent name
has_... ... Config Config
...
Config Config Config Signal Map Signal Map

SD SD
SD SD SD
seq seq
seq seq seq

M M B M B M B M B M B

DUT xbus xbus

xbus

At first glance, you can see the architecture of the XBus eVC is very similar to the XSerial eVC. There
is an env encapsulating configuration fields, signals, and several agents, and the agents are organized
internally in a similar way to the XSerial agents.

However, the XBus protocol is more complex than the XSerial, and this is reflected in the various types
of XBus agents. The agents here can play the roll of a bus master (initiating activity on the bus), a bus
slave (responding to bus master requests but not initiating activity), and an arbiter (coordinating between
the masters so that only one master initiates activity on the bus at a given time). The exact agents vary
for different buses, but this is a very typical arrangement.

The XBus eVC allows for a list of master agents and a list of slave agents. Thus the number of agents
instantiated can vary when the eVC is used in different situations. In the XSerial eVC, there are usually
exactly two agents, but one of them might be ignored.

There are other differences we can notice. The XBus has a bus monitor in addition to the agent monitors,
while the XSerial eVC has only agent monitors. The signals in the XBus are grouped under the env,
while in the XSerial eVC they are grouped in the agents.

From these differences, it is clear that a typical eVC architecture can have some variance and yet still be
quite similar.

e Reuse Methodology 4-13


Typical eVC Architecture
Combining eVCs

4.4 Combining eVCs


The first examples we looked at were standalone eVCs. We now look at an SoC example that combines
several eVCs. Figure 4-7 shows such a verification environment.

Figure 4-7 XSoC eVC

xsoc_env
xserial_env
xbus_env xserial_env
Config: RX Agent TX Agent
Config: MASTER SLAVE ARBITER nameConfig: RX Agent TX Agent
name Agent Agent Agent ... name Config Config
has_... ... Config Config
... Signals Signals
Config Config Config Signal Map Signal Map
Sequence
Signal Map driver SD SD
SD SD SD
seq seq
seq seq seq

M M B
B M B
B M B
B M B M B

DUT xbus xbus

xbus serial serial


dev #2 dev #1

In this case, the SoC verification environment could be the end user’s full environment. Still, we choose
to represent it as an eVC, because it highlights the fact that any verification environment today can turn
into a verification component in a bigger verification environment tomorrow.

This is the first example we see where one eVC is making use of other eVCs. The XSerial and XBus
eVCs are instantiated within the XSoC eVC. In fact, the XSoC eVC has no agents of its own, although
it probably will have some configuration that is not shown here simply because the diagram is crowded.
In this example, the DUT has two XSerial devices, and thus the XSoC eVC has a list of xserial_env
instances. Not shown in Figure 4-7 are things like the scoreboards that check the data end-to-end
between the two eVCs.

All in all, we can see that the XSoc eVC makes thorough use of the lower-level eVCs. By integrating
components, it creates a new and bigger verification component without adding much new code.

4-14 e Reuse Methodology


Typical eVC Architecture
Layering eVCs

4.5 Layering eVCs


Layering is a technique that lets generation and monitoring of traffic be split into distinct logical layers.
This enables independent control over behavior at each layer during generation and independent
observation of behavior at each layer during monitoring.

Layering is normally used in eVCs for protocols that naturally split into layers, for example, ATM over
Utopia (ATM and Utopia each being a layer), or Ethernet (as in Ethernet packets over XGMII over
XSBI).

Layered eVCs provide a flexible, scalable, and reusable approach to implementation of verification
solutions for multi-layer protocols. You can deliver a separate eVC for each layer or a combined eVC
with functionality for all layers.

Single-layer eVCs can be written without the need for prior knowledge of which other layer eVCs they
might be used with. The protocol for interconnection can be separately encapsulated in connector code,
which in turn can be delivered as a separate eRM package.

Any eRM-compatible eVC can be used as a lowest-layer eVC. Higher-layer eVCs require a
method-based API (but can optionally have an additional signal-based API).

Throughout this section, the example is of ATM over XSerial.

This section contains:

• “Typical Layering Applications” on page 4-15


• “Requirements for Lower-Layer eVCs” on page 4-16
• “Requirements for Higher-Layer eVCs” on page 4-17
• “Inter-Layer Connection” on page 4-18
• “Partitioning of Layers and Connections Between Packages” on page 4-21
• “Separation of Control in Multi-Layer Sequences” on page 4-21

See Also
• Verisity ATM eVC Overview (vr_atm_overview.pdf) in the erm_lib/vr_atm/docs directory
• Verisity XSerial eVC Overview (vr_xserial_overview.pdf) in the erm_lib/vr_xserial/docs directory

4.5.1 Typical Layering Applications


There are two common forms of layered eVCs: single-layer eVCs and multi-layer eVCs.

e Reuse Methodology 4-15


Typical eVC Architecture
Requirements for Lower-Layer eVCs

• Single-layer eVCs provide functionality relating to a single layer in a protocol, but they also provide
hooks to let other protocol layers be connected above or below as appropriate. Such eVCs enable a
plug-and-play approach to building multi-layer solutions.
• Multi-layer eVCs combine two or more protocol layers in a single eVC using a layered approach.
Such eVCs provide a single-package solution for a multi-layer protocol while letting the user get
control and visibility at each protocol layer.

The decision about which approach to take (single-layer or multi-layer) depends on the specific
protocol(s) in question. There may be both commercial and technical aspects to this decision.

In this chapter, we describe the single-layer approach in detail and provide some discussion of how the
same techniques can be applied to multi-layer eVCs.

Example code is drawn from the Golden eVCs for demonstrating how to layer ATM over XSerial:

• The code for the ATM eVC (an example of a higher-layer eVC) can be found in the erm_lib/vr_atm
directory.
• The code for the XSerial eVC (an example of a lowest-layer eVC) can be found in the
erm_lib/vr_xserial directory.
• Example code for the connection between the ATM and XSerial eVCs can be found at
erm_lib/vr_xserial/examples/layering_atm. Example code for the connection between the ATM
and XBus eVCs can be found at erm_lib/vr_xbus/examples/layering_atm.

4.5.2 Requirements for Lower-Layer eVCs


Lower-layer eVCs must be able to communicate with the DUT in the normal way via some form of
signal interface. They also must have sufficient hooks to allow connection to higher-layer eVCs.

For data being generated by a higher-layer eVC and then driven into the DUT via the lower-layer eVC,
the connection between the layers is achieved through the sequence interface. Lower-layer eVCs are
required to have a standard sequence interface implemented using Pull Mode. The connection between
the layers is then implemented as one or more special connector sequences.

For data being collected from the DUT by the lower-layer eVC and passed to the higher layer eVC, the
connection between the layers is achieved through the scoreboard hooks. Lower-layer eVCs are required
to have sufficient scoreboard hooks that the higher-layer eVC can extend to extract the data that it
requires.

Any standard, eRM-compatible eVC can be used as a lowest-layer eVC in a layered solution without
modification so long as its sequence drivers use Pull Mode.

4-16 e Reuse Methodology


Typical eVC Architecture
Requirements for Higher-Layer eVCs

4.5.3 Requirements for Higher-Layer eVCs


Higher-layer eVCs have one significant difference from lowest-layer eVCs – they normally do not have
a mechanism for driving and sampling signals in the DUT. Instead, a higher-layer eVC provides a set of
method calls that allow transfer of data to and from a lower-layer eVC.

In some cases, an eVC might need to be capable of acting either as a higher-layer eVC or as a
lowest-layer eVC. For example, an XGMII (Ethernet) eVC might be used to layer over an XSBI eVC to
generate and collect XGMII layer data while connected to an XSBI protocol DUT. However, the same
eVC might be connected directly to XGMII signals for a DUT that has an XGMII port. In such cases, we
recommend that the agent have method calls suitable for use in layering the eVC over lower-level eVCs.
The env can then have an optional signal-based interface that calls the methods in the agent as
appropriate.

Typically, two method calls are provided, one for passing data in each direction. Normally, these are
placed in the env unit of the higher-layer eVC. However, it is legal to place them either in the agent unit
or the BFM unit (for the higher-to-lower-layer direction) and in the monitor unit (for the
lower-to-higher-layer direction). When deciding where to locate these methods, bear in mind the likely
use model for the higher-layer eVC, and try to choose an interface that is intuitive for users.

Note These method calls are always called from the lower layer eVC. Hence, both eVCs are operated
in Pull Mode.

When designing the method interfaces, ensure that they are sufficiently flexible to support any possible
lower-level protocol. For example, although it might seem sensible for a method call for an ATM eVC
to work with data partitioned into bytes, this might not be suitably flexible when layered over a
lower-layer eVC that transfers data one bit at a time. Similarly, a lower-layer eVC that can transfer data
32 bits at a time should not have to call the ATM eVC’s method interface four times for each transfer. As
a general rule, method calls should pass a list of bits so that the lower-layer eVC can decide how much
data to request/return at a time.

The following code examples illustrate a typical method interface for an ATM eVC. Two methods are
provided, one for each direction of data flow:

• get_cell_data(n : uint, first : *bool) : list of bit @sys.any is undefined;


• collect_rx_cell_data(d : list of bit, first : bool) is undefined;
The get_cell_data() method should be called by a lower-layer eVC to obtain ATM cell data from the Tx
path of the ATM eVC. The parameter n indicates how many bits of data should be supplied. The
appropriate number of bits is returned as a list. If the first bit of this list represents the start of an ATM
cell then the first parameter is returned as TRUE. If there is cell data left from a current cell and n is
larger than the number of remaining bits, then the returned list of bits only contains the remainder of the
current cell. To obtain the beginning of the next cell, this method must be called again. If no cell data is
available, then an empty list is returned and the first parameter will be FALSE.

e Reuse Methodology 4-17


Typical eVC Architecture
Inter-Layer Connection

The collect_rx_cell_data() method should be called each time some cell data is detected by a lower
layer on the Rx Path. The d parameter should contain the latest fragment of the bit list for the cell, and
first should be TRUE if this is the beginning of a cell. The d parameter should consist only of data from
a single cell. Any data that pushes the current cell over the 53-byte limit will be discarded.

4.5.4 Inter-Layer Connection


To connect two layers:

1. Create the necessary pointer(s) to the upper layer in the lower layer.

2. Connect received traffic by extending the Rx monitor’s scoreboard hook in the lower layer to call
the appropriate method in the higher layer.

3. Create the connector sequence(s) for the lower layer sequence driver that takes appropriate data from
the higher layer.

The rest of this section examines each of these steps in more detail:

• “Step 1: Pointers to the Upper Layer” on page 4-18


• “Step 2: Rx Monitor’s Scoreboard Hook” on page 4-19
• “Step 3: Connector Sequences” on page 4-19

4.5.4.1 Step 1: Pointers to the Upper Layer


The upper layer does not need to know anything about the lower layer, but the lower layer must know
about the upper layer. For that, a pointer is typically placed either in the env or the agent of the lower
layer. A copy of this pointer might need to be propagated to other units within the lower layer (most
notably the sequence driver).

Note The addition of the pointer(s) must not compromise the standalone behavior of the lower layer.

Example
extend vr_xserial_tx_driver_u {
atm_evc : vr_atm_env_u;
};

extend vr_xserial_agent_u {
atm_evc : vr_atm_env_u;
keep soft atm_evc == NULL;
when ACTIVE has_tx_path vr_xserial_agent_u {
keep tx_driver.atm_evc == sn_pre_t(atm_evc);
};

4-18 e Reuse Methodology


Typical eVC Architecture
Inter-Layer Connection

};

4.5.4.2 Step 2: Rx Monitor’s Scoreboard Hook


When extending the Rx monitor’s scoreboard hook, consider the granularity with which data is passed
to the higher layer.

Example
extend vr_xserial_agent_u {
rx_frame_completed(frame : vr_xserial_frame_s) is also {
if atm_evc != NULL {
if frame.payload is a ATM vr_xserial_frame_payload_s (d) {
atm_evc.collect_rx_cell_data(pack(packing.low,
d.data), d.first);
};
};
};
};

4.5.4.3 Step 3: Connector Sequences


Creating a connector sequence for the lower layer sequence driver that takes data from the higher layer
is potentially the most complex step in creating a layered eVC architecture.

The underlying principle is to create a sequence that drives appropriate lower-layer data according to
data acquired from the higher layer. There can be multiple valid ways of doing this. For example, when
layering ATM over XSerial, the connector sequence might send a single XSerial frame containing a
fragment of an ATM cell, or the connector sequence might send multiple XSerial frames making up a
complete ATM cell. Often it makes sense to create a library of connector sequences that address
different testing scenarios.

In many cases, connector sequences embody protocol factors that are specific to the layering of the two
protocols. For example, neither the XSerial nor the ATM specifications specify how to layer ATM over
XSerial. In this case a separate specification is required to indicate how ATM cells should be transported
over an XSerial link. It is this method of transportation that is typically encoded by the connector
sequence.

An additional issue is that the higher-layer method that supplies data to the lower layer will, of necessity,
be a TCM. At best, this TCM will consume Specman tick time. At worst, it can consume real simulator
time. For example, a wait statement in a higher-layer sequence can cause a call to driver.get_next_item()
in the higher-layer BFM to stall. That, in turn, might cause the higher-layer interface TCM to consume
simulator time.

e Reuse Methodology 4-19


Typical eVC Architecture
Inter-Layer Connection

Constraints associated with a do action in the lower-layer sequence are not allowed to consume time. As
such, a mechanism is required to delay the do pending the return of data from the higher layer. This is
typically achieved using the connector sequence’s pre_do() TCM. This TCM gets called immediately
before each do action in the sequence and can be used to delay the do while data is collected from the
higher layer. Typically, the code in the pre_do() TCM calls the higher-layer TCM to obtain the
higher-layer data and stores this locally within the sequence. The do action can then constrain the
lower-layer data item according to this locally stored data.

The following code illustrates a typical connector sequence. This sequence sends a single ATM XSerial
frame containing ATM data if such data is available. If no ATM data is available, then the sequence
sends an IDLE frame.
extend ATM_FRAME_CONNECTOR vr_xserial_tx_sequence {

-- This is the ATM cell data in raw format.


!raw_data : list of bit;

-- This field is TRUE if raw_data contains the start of an ATM cell.


!first : bool;

-- This is the actual packed data as stored in the XSerial frame


-- payload.
!payload_data : uint(bits:7);

pre_do(is_item : bool) @sys.any is also {


if is_item {
if driver.atm_evc == NULL {
error("Attempting to do ATM sequence,
but driver's atm_evc field is NULL");
};
raw_data = driver.atm_evc.get_cell_data(7, first);
payload_data = pack(packing.low, raw_data);
};
};

body() @driver.clock is only {


do frame keeping {
soft it.payload.frame_format == MESSAGE;
raw_data.size() > 0 => it.payload.frame_format == ATM;
it.payload is a MESSAGE vr_xserial_frame_payload_s (p) =>
p.message == IDLE;
it.payload is a ATM vr_xserial_frame_payload_s (p) =>
(p.data == payload_data) and (p.first == first);
};
};
};

4-20 e Reuse Methodology


Typical eVC Architecture
Partitioning of Layers and Connections Between Packages

4.5.5 Partitioning of Layers and Connections Between


Packages
Following are three situations in which eVCs might be layered.

Independent eVCs
The most general case for layering is as follows:

• Higher-layer eVC is supplied by vendor/developer 1.


• Lower-layer eVC is supplied by vendor/developer 2.
• Connection between layers is supplied by vendor/developer 3.
In this situation, the higher- and lower-layer eVCs, provide the relevant hooks to enable layering, but
normally would not contain any code relating to the connecting of these two specific protocols. As such,
it is important that the layer eVCs provide all required hooks as part of their published APIs. It is also
important that the connection code does not use anything other than the published APIs. In such cases,
the inter-layer connection can be part of an end-user verification environment or it can be delivered as a
separate eRM package.

Dependent eVCs
Sometimes the layer eVCs can be written knowing that layering between them will take place. In such
cases, it might be appropriate to build the layering code into one of the individual layer eVCs (typically
the higher-layer eVC).

Layering within Single eVC


In certain cases, it might not make sense to deliver the individual layers as separate eVCs. In such cases,
a multi-layer eVC might be the most appropriate vehicle for delivery. In a multi-layer eVC, each layer
will be handled by one or more layer-specific agents, for example, layer_1_agent, layer_2_agent, etc.
Each agent is essentially the same as in the multiple-eVC implementation — the only difference being
that all agents for all layers would be contained in a single env. The developer might want to provide
flags to allow selective enabling/disabling of layers.

4.5.6 Separation of Control in Multi-Layer Sequences


Once a protocol is divided so that there is a sequence driver at each layer, control over scenario
generation becomes significantly more flexible. By default, a lower-layer eVC in a multi-layer
environment is configured to perform continuous connector sequences. As such, scenarios can be
written at higher layers and the lower layer data is automatically created.

e Reuse Methodology 4-21


Typical eVC Architecture
Modeling FAQs

Specific lower-layer behavior can be achieved by writing sequences that mix connector sequences with
other required behavior (such as error conditions).

For more coordinated testing, a virtual sequence driver can be used to regulate traffic injection at each
layer. For example, a virtual sequence could be written to drive continuous ATM cells over an XSerial
link while occasionally grabbing the XSerial sequence driver to override the default connector sequence
with one that introduces XSerial-specific error conditions.

4.6 Modeling FAQs


Many of the differences between the two sub-eVCs (XSerial and XBus) and the way they are used raise
interesting architecture questions.

Q: If the DUT has N ports of same protocol, should we have 1 env with N agents, or N envs each with
single instance agents? For example, if a DUT has two pairs of serial ports, which of the following
arrangements is better?

xserial_env xserial_env
or xserial_env
RX TX
RX TX RX TX
Agent Agent Agent Agent

A: It depends on the protocol:

• In case of serial interface, typically each pair of ports is independent and has 2 agents in it (RX/TX).
Therefore it is natural to have two envs (as shown on the right side of the above figure).
• In buses, typically there are many agents on a bus. Thus if the DUT has one bus, it is natural to have
a single env for all N agents (as shown on the left side of the above figure).

Q: If an env has a single agent, should env and agent be merged (that is, have only an env unit with no
agent in it)?

x_env
or x_env
X Agent

A: They should be kept separate (as shown on the left side of the above figure).

• It is okay to have a single agent in env. It will probably be more reusable this way.
• It is okay to have zero agents in an env. For example, SoC has envs in it but no agents.
Q: Must the Monitor and BFM be units under the env/agent? Might they be TCMs?

A: It is better to have them as units, not as TCMs.

4-22 e Reuse Methodology


Typical eVC Architecture
Terminology

• For small environments, having them as TCMs might make sense, but for big environments it can
create problems. Therefore, for uniformity, they should be units.

4.7 Terminology
The following sections provide definitions of terminology. These terms are used extensively in this
book, and as many of these terms are used slightly differently by different people, be aware of the
specific connotations we give to each of them.

This section includes:

• “Main Entities” on page 4-23


• “Sub-Entities” on page 4-24
• “Agent Types” on page 4-25
• “Full Legend for Architecture Diagrams” on page 4-26

4.7.1 Main Entities


DUT Device Under Test, the device to be verified (typically an HDL design).

In any given verification environment, there is only one DUT. (Even if the
env is composed of several envs, each with its separate DUT block, still in
the full env, the total of all blocks should be considered one DUT.)

Package An independent and modular eVC, utility, or shareware.

e Reuse Methodology 4-23


Typical eVC Architecture
Sub-Entities

Data Item An e object that corresponds to a specific data structure in the eVC
architecture.

Data items are implemented as structs.

Data item examples: packet, transaction, instruction, and so on.

Env The root unit for an independent verification environment, for a well defined
protocol, interface, specification, or HW block.

When combining HW blocks to HW systems, the envs can also be combined


by nesting block envs into the system env.

Each eVC defines an evc_env (child of any_env).

Multiple bus instances in the DUT imply multiple eVC instances (envs).

Agent An e object that represents a device or similar entity in a verification


package (for example, master, slave, TX/RX machine).

Agents are implemented as units and contain a BFM, sequence driver,


sequences, and a monitor.

4.7.2 Sub-Entities
Monitor A passive entity that samples the DUT signals (but does not change their
values at any time).

Functionality: Extracts events, prints traces, collects transaction and data


items, does checking and coverage.

BFM An active entity that emulates an auxiliary device for the DUT.

Functionality: Samples and drives the DUT signals.

Always instantiated inside agents (a unit)

Monitor-BFM Relations
BFMs and Monitors are typically built independently (even if they look at the same signals). Therefore
each can work without the other.

4-24 e Reuse Methodology


Typical eVC Architecture
Agent Types

Monitor-BFM Guidelines
• It is okay for eVC developers to duplicate or reuse some common code.
• Within an agent, monitors must not depend on the presence of a corresponding BFM.
• Within an agent, BFMs might depend on the presence of a corresponding monitor.

4.7.3 Agent Types


Agents can be of two types (ACTIVE or PASSIVE):

ACTIVE Drives signals into the DUT.

• Proactive Initiates transactions and send them to the DUT.

• Reactive Reacts to transactions as they come from the DUT.

PASSIVE Looks at HW blocks internal to the DUT (often with no external interface).
Can also collect transactions from the DUT, but it does not drive signals.
BFM and sequence drivers are disabled.

Agent Examples

eVC Proactive Reactive PASSIVE

AHB eVC master eVC slave

USB host device

XSerial TX (RX) (RX)

Note All agents in an eVC can be used as PASSIVE agents.

4.7.4 Data Item Naming Convention


Each communication protocol has a basic data item that is generated and sent by the BFM and collected
by the monitor. Following is the recommended naming convention for the type of the basic data item:

package-name_agent_[driven|monitor]_item-name

e Reuse Methodology 4-25


Typical eVC Architecture
Full Legend for Architecture Diagrams

For example, vr_xbus_master_driven_burst is the burst generated and sent by the master.
vr_xbus_slave_monitor_burst is the burst reconstructed by the monitor in the slave. The types can be
inherited from a common type using like inheritance. If the types are closely related, when inheritance
might be more applicable.

4.7.5 Full Legend for Architecture Diagrams


Figure 4-8 Full Legend for Architecture Diagrams

Struct struct Data flow

Data item
DUT access DUT
Unit unit

Sequence Driver
Enclosing unit
Unit instantiation Monitor
Instantiated unit Color
BFM
DUT
Enclosing unit
Subtype Subtype
Sequence execution—
seq
Struct/unit pointer struct unit Sequential: seq
seq

Topic: seq
Field grouping field 1 Parallel: seq
field 2 seq

Event

4-26 e Reuse Methodology


5 Sequences: Constructing Test
Scenarios
This chapter describes a uniform and efficient way of implementing sequences in Specman. Specifically,
this chapter introduces a new statement (the sequence statement), a new action (the do action), and a
whole methodology for handling sequences.

Together with the evc_util package, Verisity ships three example packages called ex_atm, ex_c_bus, and
ex_soc. These example packages demonstrate in detail the various sequence features.

Note You can only run these example packages on top of Specman version 4.1 or higher. See the
PACKAGE_README.txt files of the example packages for a description of how to run them.

The sections of this chapter can be divided into the following four main parts:

Introduction • “Introduction to Sequences” on page 5-2


• “How to Use Sequences in Your Environment” on page 5-4
Basic Use • “Getting Started with Sequences” on page 5-5
• “Implementing Sequences” on page 5-11
• “Writing Tests Using Sequences” on page 5-20
• “Sequence File Organization” on page 5-24

e Reuse Methodology 5-1


Sequences: Constructing Test Scenarios
Introduction to Sequences

Advanced Use • “Using Virtual Sequences” on page 5-25


• “Advanced Generation-Related Aspects of Sequences” on page 5-31
• “Implementing Complex Scenarios” on page 5-35
• “Miscellaneous Advanced Features” on page 5-46
• “Layering of Protocols” on page 5-52
• “Tracing and Debugging Sequences” on page 5-67
Reference • “Sequence-Related Methods” on page 5-72
• “Sequence-Related Pseudo-Routines” on page 5-80
• “Sequence Interface” on page 5-82
• “Predefined Sequence Kinds” on page 5-89
• “BFM-Driver-Sequence Flow Diagrams” on page 5-91
• “Sequence Deprecation” on page 5-96
• “Known Limitations” on page 5-99

5.1 Introduction to Sequences


Sequences let you define streams of data items sent to a DUT (or streams of actions performed on a DUT
interface). You can also use sequences to generate static lists of data items with no connection to a DUT
interface.

For defining sequences, it is also necessary to define standard interfacing entities between the sequence
and the DUT. Therefore, the sequence solution deals with three main entities:

Item A struct that represents the main input to the DUT (for example, packet,
transaction, instruction). Typically, such items already exist in your
environment, and only very small modification is required to use them with
sequences.
Sequence A struct that represents a stream of items signifying a high-level scenario of
stimuli. This is done by generating items one after the other, according to
some specific rules. The sequence struct has a set of predefined fields and
methods. The sequence struct can also be extended by the user.

5-2 e Reuse Methodology


Sequences: Constructing Test Scenarios
Introduction to Sequences

Sequence Driver A unit that serves as the mediator between the sequences and the
verification environment. The generated items are passed from the sequence
to the sequence driver and the sequence driver acts upon them one by one,
typically passing them to some kind of BFM (Bus Functional Model). Of
course, the sequence driver can be rather empty and, instead of driving items
into the DUT, simply place them on a list.

To complete the picture:

• A TCM does the actual driving of items into a specific DUT channel.
• The TCM resides in a BFM unit.
• For the purpose of driving data into the DUT, the sequence driver interacts only with the BFM.
The sequence driver and the BFM work as a pair, where the sequence driver serves as the interface
upwards towards the sequences so that the sequences can always see a standard interface to the DUT.
The BFM serves as the interface downwards to the DUT, letting you write sequences in any way you
find appropriate.

At first, it might seem unnecessary to separate the sequence driver and the BFM. The importance of this
separation becomes clear when implementing virtual sequences (see “Using Virtual Sequences” on page
5-25).

Figure 5-1 describes the general flow of data and control in sequences.

e Reuse Methodology 5-3


Sequences: Constructing Test Scenarios
How to Use Sequences in Your Environment

Figure 5-1 Flow of Control and Data in Sequences

TX Agent Fields:
id
Sequence kind == TX
Config: Item backpointer
...
...

Sequence Driver
seq

seq
Clock Event
seq
seq

seq
Signal Map

Mon BFM

DUT

The execution flow for generation of items and driving them into the DUT is as follows:

• The sequence driver launches the main TCM of a sequence (called body()), which in turn launches
the main TCM of any subsequences. (See “Defining the Behavior of Sequences” on page 5-12.)
• Sequences generate items on the fly (as part of the execution of their body() TCM).
• Each generated item is passed to the sequence driver, which in turn passes it to the BFM.
Note All of the above actions are done automatically by the sequence mechanism. The subsequence
and item actions are encapsulated in the new do action. (See “Activating Items and Subsequences” on
page 5-13.)

5.2 How to Use Sequences in Your Environment


To use sequences in your environment:

1. Define the sequence item struct.

2. Define the sequence and its driver using the sequence statement.

3. Hook the sequence driver to the environment.

5-4 e Reuse Methodology


Sequences: Constructing Test Scenarios
Getting Started with Sequences

4. Create your sequence library by implementing various scenarios using the sequence struct.

5. Write tests based on the sequence library.

For more information on Step 1 through Step 3, see “Getting Started with Sequences” on page 5-5.

For more information on Step 4, see “Implementing Sequences” on page 5-11.

For more information on Step 5, see “Writing Tests Using Sequences” on page 5-20.

Throughout these sections, the examples used are from the eRM library.

5.3 Getting Started with Sequences


This section describes how to define sequences in your environment and hook them to your BFM.

This section includes:

• “Defining the Sequence Item” on page 5-5


• “Defining the Sequence and Its Driver Using the sequence Statement” on page 5-5
• “Hooking the Sequence Driver to the Environment” on page 5-9

5.3.1 Defining the Sequence Item


For an item to be used with sequences it must have some common functionality. Therefore, define the
item struct like you always do but inherit from the predefined type any_sequence_item.

For example:
struct ex_atm_cell like any_sequence_item {
kind: [A1, A2, A3, A4];
color: ex_atm_color;
..
};
Note If you have a pre-existing environment that does not use sequences, you must edit the basic item
to make it inherit as above.

5.3.2 Defining the Sequence and Its Driver Using the


sequence Statement
Define the sequence struct and the sequence driver unit using the sequence statement.

e Reuse Methodology 5-5


Sequences: Constructing Test Scenarios
Defining the Sequence and Its Driver Using the sequence Statement

Syntax
sequence sequence_name [using sequence_option,...];

Options
item = item_type The item to be used in the sequence. This item must be already
defined and inherits from any_sequence_item. The item struct
is extended by the sequence statement.

If the item option is not used, then this is assumed to be a virtual


sequence (see “Using Virtual Sequences” on page 5-25).
created_kind = kind_name The name of the associated kind enumerated type to be created
(default: sequence_name_kind).
created_driver = driver_name The name of the associated sequence driver to be created
(default: sequence_name_driver).
sequence_type = The name of the sequence struct your sequence inherits from
base_sequence_name (default: any_sequence).

For more information, see “Creating a Common Base for Your


Sequences and Sequence Drivers” on page 5-46.
sequence_driver_type = The name of the sequence driver unit your sequence driver
base_sequence_driver_name inherits from (default: any_sequence_driver).

For more information, see “Creating a Common Base for Your


Sequences and Sequence Drivers” on page 5-46.

Example 1 Defining a BFM sequence for ATM cells


sequence ex_atm_sequence using item=ex_atm_cell;

This statement assumes that an ex_atm_cell struct already exists. It defines:

• Struct ex_atm_sequence (inherits from any_sequence)


• Type ex_atm_sequence_kind
• Unit ex_atm_sequence_driver (inherits from any_sequence_driver)

Example 2 Defining a virtual sequence for an SoC environment


sequence soc_sequence;

This statement defines the soc_sequence struct, the soc_sequence_kind type, and the
soc_sequence_driver unit.

5-6 e Reuse Methodology


Sequences: Constructing Test Scenarios
Defining the Sequence and Its Driver Using the sequence Statement

For more information about virtual sequences, see “Creating a Virtual Sequence” on page 5-26.

The rest of this section describes the entities that the sequence statement creates or extends:

• “Sequence Struct” on page 5-7


• “Sequence Driver Unit” on page 5-7
• “Item Struct” on page 5-8
• “Sequence Kind Type” on page 5-8

5.3.2.1 Sequence Struct


The sequence statement creates a new sequence struct (ex_atm_sequence in “Example 1” on page 5-6),
which inherits from the predefined any_sequence, which in turn inherits from any_sequence_item.

The main members of the created sequence struct are:

driver: driver_name; Reference to the sequence driver.


kind: kind_name; For creating sequence subtypes with various behavior.
body() @driver.clock is empty; Defines the sequence behavior to be implemented by
the user.
parent_sequence: sequence_name; Backpointer to the creating sequence of the sequence.
Assigned automatically in pre_generate() of the
sequence if such a parent exists.

Note The only way to define sequences is via the sequence statement; however, you can define a base
sequence by deriving it from any_sequence. For more information see “Creating a Common Base for
Your Sequences” on page 5-47.

For the full list of the sequence struct members, see “any_sequence Interface” on page 5-83.

5.3.2.2 Sequence Driver Unit


The sequence statement creates a new sequence driver unit (ex_atm_sequence_driver in “Example 1” on
page 5-6), which inherits by default from any_sequence_driver.

The main members of the created driver unit are:

e Reuse Methodology 5-7


Sequences: Constructing Test Scenarios
Defining the Sequence and Its Driver Using the sequence Statement

sequence: MAIN sequence_name; The MAIN sequence, whose body is started


automatically at the beginning of the run phase
event clock; Main clock for the sequences (to be implemented by
the user)
get_next_item(): item_name @clock Method used to get the next item to be created by the
sequences
event item_done Event emitted to inform the sequence driver that the
BFM is ready for the next item

Notes
• Some of the above methods apply only for BFM sequence drivers and not for virtual sequence drivers.
For more information about virtual sequences, see “Using Virtual Sequences” on page 5-25.
• The only way to define sequence drivers is via the sequence statement; however, you can define a
base sequence driver by deriving it from any_sequence_driver. For more information, see “Creating
a Common Base for Your Sequence Drivers” on page 5-48.

For the full list of the sequence driver unit members, see “any_sequence_driver Interface” on page 5-85.

5.3.2.3 Item Struct


The sequence statement does not create the item struct, but it extends it.

The main members that are added to the item struct are:

driver: driver_name; Reference to the sequence driver that facilitates the


actual driving to the DUT.
parent_sequence: sequence_name; Backpointer to the creating sequence of the item.
Assigned automatically in pre_generate() of the
item.

For the full list of the item struct members, see “any_sequence_item Interface” on page 5-82.

5.3.2.4 Sequence Kind Type


The sequence statement creates a new kind enumerated type called “sequence_name_kind”
(ex_atm_sequence_kind in “Example 1” on page 5-6), which has the following predefined values:

5-8 e Reuse Methodology


Sequences: Constructing Test Scenarios
Hooking the Sequence Driver to the Environment

MAIN A sequence that loops n times creating the sequence field (randomly unless
constrained). The driver contains an instance of the MAIN sequence, which is
started automatically upon run().
RANDOM Same as MAIN but used inside other sequences.
SIMPLE A sequence that contains a single item.

Note Verisity recommends that all enumerated values be stated in uppercase letters. In addition, all
user-defined sequence kinds should be defined as uppercase names. For example:
extend ex_atm_sequence_kind: [LEGAL_CELLS];
extend LEGAL_CELLS ex_atm_sequence {
body() @driver.clock is only { ... };
};
extend MAIN ex_atm_sequence {
body() @driver.clock is only { ... };
};

For more information, see “Predefined Sequence Kinds” on page 5-89.

5.3.3 Hooking the Sequence Driver to the Environment


To hook the sequence driver into your environment:

1. Add a reference to the sequence driver in the BFM.

2. Instantiate the sequence driver in the environment.

3. Connect the sequence driver’s clock to the BFM’s clock.

4. Transfer the item from the driver to the BFM by adding a TCM that explicitly requests items from
the driver and calls the appropriate BFM’s TCM.

5. (Optional) Add useful fields and methods to the base sequence type.

Hookup Example
Assume an ex_atm_cell item that is defined as follows:
struct ex_atm_cell like any_sequence_item {
...
};

Have a BFM that knows how to drive a cell into the DUT:
unit ex_atm_bfm {

e Reuse Methodology 5-9


Sequences: Constructing Test Scenarios
Hooking the Sequence Driver to the Environment

event a_clock is rise('atm_clk') @sim; // ATM main clock


drive_cell(cell: ex_atm_cell) @a_clock is { // drives cells to the DUT
...
};
};

The BFM is instantiated in an ATM verification environment:


unit ex_atm_agent {
bfm: ex_atm_bfm is instance;
};

Now define the ATM sequence and sequence driver, and hook the sequence driver into the BFM:
// Define ex_atm_sequence, ex_atm_sequence_kind, and ex_atm_driver
sequence ex_atm_sequence using item=ex_atm_cell,
created_driver=ex_atm_driver;

Then hook the sequence into the environment:


// 1. Add a reference to the sequence driver in the BFM
extend ex_atm_bfm {
driver: ex_atm_driver;
};

// 2. Instantiate the sequence driver in the ATM environment


extend ex_atm_agent {
driver: ex_atm_driver is instance;
keep bfm.driver == driver;
};

// 3. Connect the (predefined) clock event to the BFM's clock


extend ex_atm_bfm {
on a_clock {
emit driver.clock;
};
};

// 4. Pull item from driver, process it, then inform using item_done
extend ex_atm_bfm {
execute_items() @clock is {
var seq_item: ex_atm_cell;
while TRUE {
seq_item = driver.get_next_item();
drive_cell(seq_item);
emit driver.item_done;
};
};

5-10 e Reuse Methodology


Sequences: Constructing Test Scenarios
Implementing Sequences

run() is also {
start execute_items();
};
};

Step 5 is optional:
// 5. Extend the base ex_atm_sequence type
extend ex_atm_sequence {
!cell: ex_atm_cell;
};

At this point, your environment is already capable of generating (by default) random sequences.

• The sequence driver generates the MAIN sequence and starts its body() method upon run().
• The launched MAIN sequence creates count sequences of any kind, randomly selected from the
currently loaded ATM sequences. (count is a field in the predefined MAIN sequence.) Initially, this
is only the SIMPLE sequence, so you will have a random stream of ATM cells. See also “MAIN
Sequence” on page 5-90.

• The execute_items() TCM of the BFM pulls the items created by the sequences and drives them into
the DUT using the drive_cell() TCM.
• After each item is driven to the DUT, the event driver.item_done is emitted to let the sequence
complete the do action and inform the driver that the item was processed.
Note If your verification environment contains several ex_atm_unit instances, each of them will have
a sequence driver and hence a MAIN sequence and a random stream.

See Also
• “BFM-Driver Interaction Mode” on page 5-44

5.4 Implementing Sequences


This section describes how to implement various scenarios using the sequence struct and its related
methods and features. It then describes how to build your sequence library, which will be used later in
tests.

This section includes:

• “Implementing a Scenario Using the Sequence Struct” on page 5-12


• “Creating a Sequence Library” on page 5-19

e Reuse Methodology 5-11


Sequences: Constructing Test Scenarios
Implementing a Scenario Using the Sequence Struct

5.4.1 Implementing a Scenario Using the Sequence Struct


A sequence can be defined by the set of items that it creates. These items can be created directly by the
sequence or indirectly by creating subsequences (sequences within sequences) that in turn create items.
Creation of items/subsequences is done in a dedicated predefined TCM named body(), using the
dedicated do action.

This section includes:

• “Defining the Behavior of Sequences” on page 5-12


• “Activating Items and Subsequences” on page 5-13
• “Stopping Sequences in the Middle” on page 5-15
• “Parameterizing Sequences” on page 5-16
• “Enhancing the User Interface” on page 5-17

5.4.1.1 Defining the Behavior of Sequences


The body() TCM is a predefined TCM of any_sequence that is implemented to define the behavior of
the sequence. The body() TCM of the MAIN sequence that is generated directly under the sequence
driver is launched automatically by the run() method of the sequence driver. The body() of any
subsequence is activated by the do action.

The body() TCM defines the life cycle of the sequence and, as such, defines the duration of the
sequences. Before body() is initiated, the predefined event started occurs. When body() is finished, the
predefined event ended occurs.

You cannot call or start body() directly. Instead, use the following:

To call the body() TCM: To start the body() TCM:


• Use the do action. • Use the any_sequence predefined method
start_sequence().
For example:
For example:
do sequence;
sequence.start_sequence();

Note The do action can be used only within a sequence TCM. For details about the additional effects
of the do action, see “Activating Items and Subsequences” on page 5-13.

Except for the aforementioned restriction, body() is just a normal TCM. You can use ordinary
procedural code in it, and you can extend it using is first, is also, or is only.

5-12 e Reuse Methodology


Sequences: Constructing Test Scenarios
Implementing a Scenario Using the Sequence Struct

When starting the body() TCM using the start_sequence(), there are two hooks, pre_body() and
post_body() TCMs, that can be used as follows:

pre_body() This lets you do any actions (time-consuming or non-time-consuming) prior


to execution of body() and, if need be, prevent the execution of body() by
calling the stop() method.
post_body() This lets you do any actions (time-consuming or non-time-consuming) after
the execution of body().

Note The MAIN sequence is started automatically, using the start_sequence() method. For more
information about the start_sequence() method, see “start_sequence()” on page 5-72.

5.4.1.2 Activating Items and Subsequences


To activate an item or a subsequence from within a sequence:
• Use the do action.

Syntax
do field_name [keeping {constraint;...}]

Parameters

field_name Must be a field in the current struct. The field must have an exclamation mark (!)
in front of it and must be either a basic item or a sequence.

constraint Can be any constraints on the field.

Description
The do action performs the following steps:

e Reuse Methodology 5-13


Sequences: Constructing Test Scenarios
Implementing a Scenario Using the Sequence Struct

On a subsequence: 1. Generates the field, considering the constraints, if any.

2. Calls its body() TCM.

The do action finishes when the subsequence body() returns.

For more information, see Figure 5-10 on page 5-93.


On an item: 1. Waits until the driver is ready to perform the do action.

2. Generates the field, considering the constraints, if any.

The item is returned by get_next_item().

The do action finishes when emitting the event driver.item_done.

For more information, see Figure 5-12 on page 5-95 and Figure 5-11 on
page 5-94.

Notes
• When do-ing an item, you must emit the event driver.item_done to let the sequence complete the do
action and inform the driver that the item was processed. (Typically, this is done when the transmission
of the item via the BFM is done.) Without emitting this event, the sequence cannot continue, and the
driver cannot drive more items.
• The do action can only be activated inside sequences.
• For items, Step 1 (waiting for the sequence driver to be ready) is performed before Step 2 (generation)
to ensure that generation is done as close as possible to the actual driving. In this way, if the constraints
depend on the current status of the DUT/environment, that status will be as accurate as possible.
• BFM sequences cannot do sequences created by other sequence statements.
• The sequence driver decides when the item is ready by managing a FIFO that also considers any
grab/ungrab actions done by the various sequences and the value of is_relevant() of the sequences.
If no grab is done, and is_relevant() returns TRUE for all sequences, the order of doing the items is
determined by the order of the do actions in the various sequences that refer to the sequence driver,
regardless of their depth or origin. Keep in mind that sequences and items can also be done in parallel,
using the all of and first of actions. (See “grab()” on page 5-74 and “is_relevant()” on page 5-78.)

do is a time-consuming action encapsulating a set of actions that can be considered as an atomic


activation of an item/sequence. However, if for some reason you want to perform any of these steps
separately from the do, you can easily do so.

Example
extend FOO ex_atm_sequence {

5-14 e Reuse Methodology


Sequences: Constructing Test Scenarios
Implementing a Scenario Using the Sequence Struct

// Parameters
i: int;
b: bool;

// Items/subsequences
!cell: ex_atm_cell;
!seq: bar ex_atm_sequence;

// The body() method


body() @driver.clock is {
do cell keeping {.len == 4};
do cell;
for i = 1 to 20 do {
do cell keeping {.address == i};
};
do seq keeping {.f == 2};
};
};

5.4.1.3 Stopping Sequences in the Middle


Sometimes, you might want to abort a sequence on occurrence of some event. For example, you might
want to run a sequence with a specific timeout. In such cases, do not use the do action within a first of
block, because the do might terminate while still interacting with the driver. Instead, use the
start_sequence() and stop() methods as follows.

To stop a sequence in the middle:

1. Generate the sequence.

For example:
extend MAIN my_sequence {
!seq: GREEN my_sequence;
body() @driver.clock is {
gen seq keeping { .driver == driver; };

2. Use the start_sequence() method to start the sequence.

For example:
seq.start();

3. Synchronize on the sequence’s ended or stopped event.

For example:
sync (@seq.ended or @seq.stopped);

e Reuse Methodology 5-15


Sequences: Constructing Test Scenarios
Implementing a Scenario Using the Sequence Struct

4. Call the sequence’s stop() method when you want to stop the run.

Example
extend MAIN my_sequence {
!seq: GREEN my_sequence;

body() @driver.clock is {
gen seq keeping { .driver == driver; };
seq.start();
sync (@seq.ended or @seq.stopped);
};
};
extend GREEN my_sequence {

body() @driver.clock is {
for i from 0 to 10 do {
do cell keeping {.color == GREEN; };
if driver.need_more_green == FALSE {
stop();
};
};
};
};

5.4.1.4 Parameterizing Sequences


Verisity recommends representing any specific behavior of the sequence by a field so that the value of
the field is the parameter for the specific feature in the sequence behavior. For example, if your sequence
creates items in a loop, then the number of iterations of the loop is a typical parameter. These parameters
can be viewed as the public interface of the sequence.

In this way, you can later control the parameters using constraints from the outside without knowing the
actual implementation of body().

For example, consider the predefined RANDOM sequence:


extend RANDOM ex_atm_sequence {
count: uint;
!sequence: ex_atm_sequence;

body() @driver. clock is {


for i from 1 to count {
do sequence;
};
};

5-16 e Reuse Methodology


Sequences: Constructing Test Scenarios
Implementing a Scenario Using the Sequence Struct

};

The parameter of this sequence is count, which is the number of random sequences that will be created
by the sequence. You can control the behavior of all RANDOM sequences in the environment by
constraining the count:
extend RANDOM ex_atm_sequence {
keep count in [10..20];
};
Note Such a constraint can also be applied locally to a RANDOM sequence field in another sequence
or even in a specific do.

5.4.1.5 Enhancing the User Interface


In addition to using the do action directly, you might want to define a more high-level interface by
encapsulating a set of actions in methods. This can be done by wrapping a do action by either methods
or macros.

Using Methods
In the sequence struct, you can define methods that encapsulate a typical do action. An example is a
read/write interface.

For example, assume that a bus-based design with the basic item c_bus_op is defined as follows:
struct c_bus_op like any_sequence_item {
kind: [READ, WRITE, OTHER];
address: int;
color: [RED, GREEN, WHITE];
when WRITE c_bus_op {
data: int; // Sent data
};
when READ c_bus_op {
!data: int; // Returned data
};
};

You can perform read operations by using the do action as follows:


do c_bus_op keeping {.kind == READ; .address == 0x100};

But sometimes it is more convenient to write something like:


write(0x100, j);
k = read(0x104);

To do that, define methods in the corresponding sequence that implement these operations:

e Reuse Methodology 5-17


Sequences: Constructing Test Scenarios
Implementing a Scenario Using the Sequence Struct

extend ex_c_bus_sequence {
!write_op: WRITE c_bus_op;
!read_op: READ c_bus_op;

// Do a c_bus write
write(address: int, data: int) @driver.clock is {
do write_op keeping {.address == address; .data == data};
};

// Do a c_bus read
// NOTE: The read operation returns a value to the sequence. This
// requires additional infrastructure in the send_to_bfm() method to
// ensure that the data on the operation will be valid after the do
// action.
read(address: int): int @driver.clock is {
do read_op keeping {.address == address};
return read_op.data;
};
};

This lets you use the convenient procedural interface while still keeping the ability to constrain other
fields (such as c_bus_op.color) from the outside.

For more information about a read/write interface, see “DUT-Independent Read/Write Interface” on page
5-41.

Using Macros
Sometimes, you might need the greater syntactical flexibility that only macros can afford.

In that case, Verisity recommends creating action macros that implement typical do actions. For
example:
define cell'action "cell <len'num> <kind'name>[ <x'num>]" as {
do cell keeping {
.len == <len'num>;
.kind == <kind'name>;
.x == <x'num|0>;
};
};

Then you can write shorthand like:


body() @driver.clock is only {
cell 2 GREEN;
for i from 1 to 20 do {
cell 3 BLUE;
};

5-18 e Reuse Methodology


Sequences: Constructing Test Scenarios
Creating a Sequence Library

};

5.4.2 Creating a Sequence Library


Once you define the sequence struct, you can create various scenarios (sequence kinds) by creating
subtypes of the sequence using the kind field. Each kind of sequence can implement a typical scenario
or a combination of existing scenarios. The set of sequence kinds is the “sequence library”.

Verisity recommends defining the sequence library in a separate file or files that can be loaded on top of
the environment. This lets you include or exclude some of the sequence kinds upon demand of specific
tests.

Note The term “subtype” applies when creating a new type using when inheritance.

To create a sequence library:

1. Extend the sequence kind type with the desired new kind.

For example:
extend ex_atm_sequence_kind: [SHORT_LONG];

2. Extend the new sequence subtype of the kind with any of the following:

• New parameters
• New implementation of body()
• Any other struct members such as constraints, methods, and so on
For example:
extend SHORT_LONG ex_atm_sequence {
// new parameter
short_count: int [1..8]; // number of short cells in sequence
// New implementation of body()
body() @driver.clock is {
for i from 1 to short_count do {
do cell keeping {.len <= 2};
};
do cell keeping {.len == 5};
};
};
Note Verisity recommends encapsulating any meaningful scenario as a new sequence kind.

3. Iterate Step 1 and Step 2 as required.

e Reuse Methodology 5-19


Sequences: Constructing Test Scenarios
Writing Tests Using Sequences

5.5 Writing Tests Using Sequences


After defining sequences and implementing several subtypes in the environment, it is time to use them.
As a sequence models the input stream of an agent, it becomes the common interface for writing tests.

Verisity recommends using sequences in tests to create a sequence library by defining many subtypes of
sequences based on the kind field of the sequence. (See “Creating a Sequence Library” on page 5-19.)
Then create tests that use these subtypes by parameterizing them, enhancing them, or using them as is
with some weights.

In some simple cases you can avoid defining new sequence kinds altogether by directly redefining the
body() method of the MAIN sequence.

Alternatively, you can define a specific new sequence kind directly in the test and then use it.

This section demonstrates all of the above options. This section includes:

• “Writing the Simplest Test: Redefining MAIN Sequence body()” on page 5-20
• “Writing a Typical Test: Using the Sequence Library” on page 5-21
• “Writing a Dedicated Test: Creating a New Sequence Kind” on page 5-23
• “Writing a Unit-Related Test: Using Unit ID” on page 5-23
Note The eRM library contains example directories with many sequence definitions and tests that you
can study and run.

5.5.1 Writing the Simplest Test: Redefining MAIN Sequence


body()
The simplest way to write tests is to redefine the behavior of the MAIN sequence by overriding its
body() method.

This is sufficient to create a test, because the MAIN sequence is started automatically as part of the
infrastructure of sequences and so there is no need to handle that in the test.

This approach is useful for creating simple directed tests.

Example
extend MAIN ex_atm_sequence {
body() @driver.clock is only {
do cell;
do cell keeping {.color == GREEN};
};
};

5-20 e Reuse Methodology


Sequences: Constructing Test Scenarios
Writing a Typical Test: Using the Sequence Library

5.5.2 Writing a Typical Test: Using the Sequence Library


The most powerful way to write tests with sequences is by creating a rich library of sequence kinds and
then using them, mixing them, slightly modifying them, and so on. Typically, the resulting tests are a
combination of all of the above. This section demonstrates two modes of use for existing sequence
kinds:

• “Writing a Random Test: Setting Weights” on page 5-21


• “Modifying an Existing Sequence” on page 5-21

5.5.2.1 Writing a Random Test: Setting Weights


The easiest and quickest way to create a test based on the sequence library is to choose a subset that will
be activated in the specific test, then set weights for each kind using keep soft … select according to the
required appearance frequency.

Example
extend MAIN ex_atm_sequence {
keep soft sequence.kind == select {
30: ALTERNATING_COLOR;
60: SHORT_LONG;
10: FIXED_LEN;
};
};

5.5.2.2 Modifying an Existing Sequence


Often, using the existing kinds is not sufficient. Sometimes it is enough to just apply additional
constraints on the sequence parameters, but sometimes you want to introduce somewhat different
behavior (for example, waiting three more cycles) into an existing sequence.

The way to modify an existing sequence is to extend the sequence subtype in the test itself.

Example
// Modify the behavior of FIXED_LEN sequence - wait additional 3 cycles
// after it ends
extend FIXED_LEN ex_atm_sequence {
body() @driver.clock is also {
wait [3] * cycle;
};
};

e Reuse Methodology 5-21


Sequences: Constructing Test Scenarios
Writing a Typical Test: Using the Sequence Library

// Use the (modified) kind in the test


extend MAIN ex_atm_sequence {
keep soft sequence.kind == select {
60: SHORT_LONG;
40: FIXED_LEN;
};
};

This approach can be used in conjunction with a specific unit. In that case, you can add a flag that
determines the behavior and then constrain the flag under the specific unit. For example, to apply the
above (waiting 3 cycles) only to sequences under unit ATM_0, extend the target_sequence within the e
file describing the current test or sequence.
// Add control to the behavior of 'fixed_len' sequence.
// Add option to wait additional 3 cycles.
// Add a unit-related constraint to activate the additional behavior.
extend FIXED_LEN ex_atm_sequence {
use_extra_waits: bool;
// Set default behavior.
keep soft use_extra_waits == FALSE;
// Activate additional behavior for ATM_0.
keep in_unit(ATM_0 ex_atm_driver) => use_extra_waits == TRUE;
};

// Implement the additional behavior under the new subtype.


extend use_extra_waits FIXED_LEN ex_atm_sequence {
body() @driver.clock is also {
wait [3] * cycle;
};
};

// Use the (modified) kind in the test.


extend MAIN ex_atm_sequence {
keep soft sequence.kind == select {
60: SHORT_LONG;
40: FIXED_LEN;
};
};
Note This is very modular, even though an existing sequence is extended inside a file describing
another sequence.

5-22 e Reuse Methodology


Sequences: Constructing Test Scenarios
Writing a Dedicated Test: Creating a New Sequence Kind

5.5.3 Writing a Dedicated Test: Creating a New Sequence


Kind
Although the recommended way of writing sequences is to use the sequence library, it is sometimes
easier to define the new kind directly in the test. This can be done when:

• You do not intend to use the sequence in any other test.


• You do not want to expose the environment to this sequence (to avoid random sequences using this
kind occasionally).

To define a sequence kind in a test, use the same methodology recommended in “Creating a Sequence
Library” on page 5-19.

Note If you redefine a sequence in several tests, consider adding that sequence to the sequence library
and using it as mentioned in “Writing a Typical Test: Using the Sequence Library” on page 5-21.

5.5.4 Writing a Unit-Related Test: Using Unit ID


Verisity recommends that units have ID fields associated with their roles within the parent unit.

These ID fields can be enumerated types (for example, ex_atm_name) or numbers (for example,
agent_num). In effect, these fields correspond to the role the field is playing. For example, you can add
to your environment a code similar to this:
type ex_atm_env_name: [NORTH, SOUTH];
extend ex_atm_env {
name: ex_atm_env_name;
};
unit comm_env {
north_atm: NORTH ex_atm_env is instance;
south_atm: SOUTH ex_atm_env is instance;
ethernet_ports: list of ethernet_port is instance;
keep for each in ethernet_ports {.ind == index};
};

These ID fields are convenient for specifying constraints for sequences and also for constraints on the
unit itself. For example:
extend NORTH ex_atm_env {
keep foo == 4;
};

Once such IDs exist, you can use methods like those mentioned in “Propagating Parameters in the
Sequence Tree” on page 5-33 and “Migrating Unit Attributes to the Sequences” on page 5-33 to apply the
IDs to the sequences themselves.

e Reuse Methodology 5-23


Sequences: Constructing Test Scenarios
Sequence File Organization

Note The name “NORTH ex_atm_env” specifies a role of ex_atm_env, sometimes mistakenly called
an instance.

This section includes:

• “Unit IDs to Constrain Sequences” on page 5-24


• “Hierarchical Unit IDs” on page 5-24

5.5.4.1 Unit IDs to Constrain Sequences


Use unit IDs to constrain sequences when the scenario depends on a particular unit.

Suppose you want to write a test in which only one ATM env will run the multi_write sequence (with an
address of 20). The rest will run random. You could achieve that as follows:
extend MAIN ex_atm_sequence {
keep in_unit(NORTH ex_atm_env) =>
soft sequence is a MULTI_WRITE ex_atm_sequence (s) and
s.address == 20;
};

5.5.4.2 Hierarchical Unit IDs


Use hierarchical IDs when roles are not unique throughout the DUT.

For example, you could define an SoC containing four comm_envs as follows:
unit SoC {
comm_envs[4]: list of comm_env;
keep for each in comm_env {.index == index};
};

You now have four NORTH ex_atm_envs. If you load your previous test on top of this environment, it
will run a multi_write sequence on each one of them. If, instead, you want to have all but the first be of
type xx, you can do that as follows:
extend MAIN ex_atm_sequence {
keep in_unit(NORTH ex_atm_env) and in_unit(comm_env) (C) and
C.index != 0 => soft sequence is an XX ex_atm_sequence;
};

5.6 Sequence File Organization


Typically, sequence implementation is split into several files:

5-24 e Reuse Methodology


Sequences: Constructing Test Scenarios
Using Virtual Sequences

Sequence definition files Define a sequence for a specific item (packet, transaction, and
so on) in any environment
DUT-specific sequence Extends the sequence for use with a specific DUT and hooks
hook file the sequence to the environment
Sequence libraries Define various sequence subtypes that implement specific
scenarios, either generic or DUT-specific
Test files Import relevant sequence libraries and use them

Note The erm_lib directory contains several full environments (see the LIBRARY_README.txt file).
However, outside the area of sequences, it is not a good example. For one thing, it defines the whole ATM
environment in one file (ex_atm_env.e) to simplify the exposition.

For more information on eVC file organization, see Chapter 3 “eVC File Organization”.

5.7 Using Virtual Sequences


BFM sequences are tightly connected to their own type and items. In other words, BFM sequences can
only do sequences of their own type or items of the type specified in the sequence statement. BFM
sequences cannot do sequences created by other sequence statements.

Virtual sequences, unlike BFM sequences, are not tightly connected to a specific sequence type or item.
Virtual sequences can do sequences of other types (but not items). As a result, you can use virtual
sequences to:

• Drive more than one agent


• Model a generic driver
A virtual sequence is driven by a virtual sequence driver, which typically has references to the individual
BFM sequence drivers. Virtual sequences can be used to synchronize and dispatch BFM sequences to
several BFM drivers.

A virtual sequence driver is not connected to a specific BFM. Therefore, it lacks the logic and
functionality of a BFM driver. For example, a virtual sequence driver does not schedule items—it only
drives sequences. As much of the driver functionality is aimed at controlling and manipulating the
scheduling of items, any method that controls this functionality cannot be called for a virtual sequence.
For example, you cannot grab/ungrab a virtual sequence driver, because grabbing manipulates the
scheduling of items. For a full list of driver interface methods that cannot be used for virtual drivers, see
Table 5-4 on page 5-85.

The following sections describe how this is done.

See also ex_soc_1_sequences.e in the ex_soc/e directory, or just load ex_soc_1_test.e (in the
ex_soc/examples directory) and run it.

e Reuse Methodology 5-25


Sequences: Constructing Test Scenarios
Creating a Virtual Sequence

This section includes:

• “Creating a Virtual Sequence” on page 5-26


• “Passing of Sequence Drivers” on page 5-27
• “Making Other Sequence Drivers Behave” on page 5-28
• “Sequences for SoC” on page 5-28
• “Transactions” on page 5-31

5.7.1 Creating a Virtual Sequence


To create a sequence that controls several sequence drivers:

1. Define a virtual sequence with a corresponding virtual sequence driver.

For example:
sequence comm_sequence; // Note no "item=" option

2. Add fields to the virtual sequence driver that point to the subdrivers.

For example:
extend comm_sequence_driver {
atm: ex_atm_master_sequence_driver;
ethernet: ethernet_sequence_driver;

3. Define the get_sub_drivers() method to return the subdrivers.

For example:
get_sub_drivers(): list of any_sequence_driver is {
return {atm; ethernet};
};
};
Note Although this method is needed by the sequence mechanism only when applying stop() on
virtual sequences, you might find the method useful for applying procedural actions on your
subdrivers. For example:
for each (d) in get_sub_drivers() {
....
};

4. Define the sequence driver in the appropriate unit in your environment (probably the lowest unit
enclosing all of the component drivers).

5-26 e Reuse Methodology


Sequences: Constructing Test Scenarios
Passing of Sequence Drivers

For example:
extend comm_subsystem_unit {
driver: comm_sequence_driver is instance;
// Constrain the subdrivers.
keep driver.atm == atm1_unit.driver;
keep driver.ethernet == ethernet_router_unit.driver;
};
The sequence driver will launch under its MAIN comm_sequence.

5. Define a clock for the sequence driver.

For example:
extend comm_sequence_driver {
event clock is only @sys.any;
};

Notes
• A virtual sequence cannot do items directly, but only sequences. To activate single items from a
virtual sequence, use the SIMPLE sequence. You can pass any desired parameters to the item by
defining the parameters as fields in the SIMPLE sequence and propagating them by constraining the
item.
• For the full list of driver interface methods that cannot be used for virtual sequences, see “Sequence
Interface” on page 5-82.

5.7.2 Passing of Sequence Drivers


By default, the driver of a called sequence (including the driver of an item that is created within a
sequence) is the driver of the calling sequence.

This is enforced via a soft constraint. However, when a virtual sequence is do-ing a BFM sequence, it
must pass the appropriate subdriver to the BFM sequence.

To pass a sequence driver for a sequence:


• Constrain the sequence driver in the keeping block of the do action.
For example:
do RWR ex_atm_sequence keeping {.driver == driver.atm};

e Reuse Methodology 5-27


Sequences: Constructing Test Scenarios
Making Other Sequence Drivers Behave

5.7.3 Making Other Sequence Drivers Behave


Suppose you create a virtual sequence driver that controls two subdrivers (as in the
ex_soc_1_sequence.e file). How do you want the subdrivers to behave while your new, virtual sequence
driver is also sending them items?

There can be three main answers:

• Business as usual:
You want the virtual sequence driver and the original sequence drivers to work at the same time,
using the built-in capability of the original sequence drivers.
This is the default behavior. There is no need to do anything to achieve this.
• Disable the subdrivers:
This is most simply achieved as follows (taken from ex_soc_1_test.e):
extend MAIN ex_atm_sequence {
keep count == 0;
};

extend MAIN ex_c_bus_sequence {


keep count == 0;
};
Setting the count to 0 means these MAIN sequences will return immediately.
Note Alternatively, you can override the body() TCM of the MAIN sequence to do nothing as
follows:
extend MAIN ex_c_bus_sequence {
body() @driver.clock is only {};
};

• Use grab() and ungrab():


Using grab() and ungrab(), a virtual sequence can achieve full control over the subdrivers for a
limited time, then let the original sequences continue working.
Note When grabbing several sequence drivers, make sure to use some convention to avoid
deadlocks. For example, always grab in a standard order.

5.7.4 Sequences for SoC


SoC environments typically require synchronization of the input of several agents, as illustrated in
Figure 5-2 on page 5-29.

5-28 e Reuse Methodology


Sequences: Constructing Test Scenarios
Sequences for SoC

Figure 5-2 eVCs within SoC Design

SD
Virtual Sequence
Mon BFM

SD
Memory DMA
Mon BFM Controller Controller
CPU Bus

Bridge System Chip


Peripheral Bus

UART GPIO USB Ethernet

SD SD SD SD

Mon BFM Mon BFM Mon BFM Mon BFM

To control a multiple-agent environment:

1. Ensure that each of the agents has its own sequence (and sequence driver).

2. Define a new (virtual) sequence (and sequence driver) using the sequence statement and omitting
the item parameter.

3. Add the existing sequence drivers as fields of the new sequence driver.

4. Pass the existing sequence drivers using constraints to the BFM sequences done by the virtual
sequence.

SoC Sequence Example


sequence comm_sequence; // Note no "item=" option
extend comm_sequence_driver {
atm_driver: ex_atm_master_sequence_driver;
eth_driver: ethernet_sequence_driver;
};

extend comm_subsystem_unit {
driver: comm_sequence_driver is instance;

e Reuse Methodology 5-29


Sequences: Constructing Test Scenarios
Sequences for SoC

keep driver.atm_driver == ex_atm_unit.driver;


keep driver.eth_driver == ethernet_unit.driver;
};

extend MAIN comm_sequence {


!atm_sequence: ex_atm_sequence;
!eth_config: ethernet_sequence;
body() @driver.clock is only {
do eth_config keeping {.driver == driver.eth_driver};
do atm_sequence keeping {.driver == driver.atm_driver};
};
};

extend MAIN ex_atm_sequence {


keep count == 0;
};-

Figure 5-3 on page 5-30 demonstrates the above example.

Figure 5-3 SoC Sequence Example

comm_subsystem_unit
Virtual Driver
do eth_config keeping {
.driver=eth_driver; eth_config
};
seq
do atm_sequence keeping { atm_sequence
.driver=atm_driver;
};

atm_env eth_env

ATM Sequence Driver Ethernet Sequence Driver


seq
seq
seq seq seq

BFM BFM

5-30 e Reuse Methodology


Sequences: Constructing Test Scenarios
Transactions

5.7.5 Transactions
The term “transaction” includes both items and sequences. In an SoC context, there can be DMA
transactions, MPEG transactions, and so on.

Such transactions normally consist of writing to several registers to initialize the DMA or MPEG device
and possibly sending an MPEG input packet to the MPEG input channel, either in parallel or after
writing to all of the registers.

It is easiest to package the transaction as a virtual sequence. Then you can have a higher-level sequence
go as follows:
do sequence keeping {.kind == DMA_TRANS};
do sequence keeping {.kind == MPEG_TRANS};

5.8 Advanced Generation-Related Aspects of


Sequences
This section explains some advanced aspects of sequences in relation to generation.

This section contains:

• “Specifying Subtype in do Actions” on page 5-31


• “Propagating Parameters in the Sequence Tree” on page 5-33
• “Migrating Unit Attributes to the Sequences” on page 5-33
• “Generating the Item/Sequence in Advance” on page 5-34
• “Constraining Complex Sequence Items” on page 5-35

5.8.1 Specifying Subtype in do Actions


When you want to do subsequences or items of known subtype(s), you can improve performance in one
of two ways:

• Statically defining the subtype of your subsequences or items


• Explicitly specifying the subtype of your subsequences or items in the appropriate do actions
When all subsequences or items are of the same subtype, then statically define the subtype. When they
are not all of the same subtype, then specify the subtype in the appropriate do actions.

e Reuse Methodology 5-31


Sequences: Constructing Test Scenarios
Specifying Subtype in do Actions

Syntax for Specifying Subtype in do Actions


do when-determinant1…n field [keeping { it. … };]

Parameters

when-determinant1…n Must be when determinants of the declared type of the field.

field The sequence or item

Note “it” already refers to the subtype. There is no need for casting to access the subtype attributes.

Example 1
extend MAIN my_sequence {
seq: my_sequence;

body() @driver.clock is {
do RED seq keeping {
it.red_level == 10; // Access red_level without casting
};
do GREEN seq keeping {
.green_level == 18;
};
do ATOMIC GREEN seq keeping {
it.green_level == 12;
it.atomic_level == PARTIAL;
};
do YELLOW seq ;
};
};

Example 2
extend MAIN my_sequence {
!seq: GREEN my_sequence;

body() @driver.clock is {
// seq will be generated to LONG GREEN my_sequence (not GREEN LONG -
// order does matter).
do LONG seq keeping {
it.length > 10; // length is a field of LONG
};
// seq will be generated to ATOMIC GREEN my_sequence
do ATOMIC seq keeping {

5-32 e Reuse Methodology


Sequences: Constructing Test Scenarios
Propagating Parameters in the Sequence Tree

it.green_level == 12;
it.atomic_level == PARTIAL;
};
};
};

5.8.2 Propagating Parameters in the Sequence Tree


Sometimes you must propagate the value of a sequence parameter (for example, unit ID) down the
sequence tree so that the root sequence (for example, the MAIN sequence) is assigned a specific value.
This value then propagates automatically to all sequences generated using do anywhere along the
hierarchy underneath the root sequence.

To propagate parameters down the sequence tree:

1. Add the parameter to the base sequence type.

2. Use the predefined field parent_sequence to propagate the value.

For example:
keep parent_sequence != NULL => soft my_param ==
parent_sequence.as_a(ex_atm_sequence).my_param;

3. Add an additional constraint for the root sequence in the root-sequence parent.

Example
type ex_atm_port_id: [ATM_0, ATM_1];

extend ex_atm_sequence {
port_id: ex_atm_port_id; // Field to be propagated
keep parent_sequence != NULL => // The propagating constraint
soft port_id == parent_sequence.as_a(ex_atm_sequence).port_id;
};

extend ex_atm_driver {
port_id: ex_atm_port_id;
keep sequence.port_id == port_id; // Constrain sequence root in driver
};

5.8.3 Migrating Unit Attributes to the Sequences


It is often good methodology to migrate unit names and attributes to corresponding sequences.

e Reuse Methodology 5-33


Sequences: Constructing Test Scenarios
Generating the Item/Sequence in Advance

To migrate unit names and attributes to corresponding sequences:

1. Define a field in the sequence struct to represent the unit attribute.

2. Migrate the value from the unit using get_enclosing_unit().

Example
extend ex_atm_sequence {
// 1. Define the unit name in the sequence.
name: ex_atm_name;
// 2. Migrate the value from the enclosing unit.
keep name == get_enclosing_unit(ex_atm_agent).name;
};

Then you can say things like:


extend NORTH MAIN ex_atm_sequence {
...
};

This is a useful shorthand. Nevertheless, you might still need to reference the IDs of the enclosing units
if you want a more complete hierarchical identification.

5.8.4 Generating the Item/Sequence in Advance


Sometimes you might want to generate or instantiate the item or sequence before the do action. You
could then use the instantiated item or sequence in the do action without regenerating it.

To generate/instantiate the item/sequence in advance:

1. Define an additional field/variable of the same type as the item/sequence.

2. Either generate the field/variable using the gen action or instantiate it using the new action.

3. Constrain the field in the do action to be equal to the additional field/variable (defined in Step 1).

For example:
extend FOO ex_atm_sequence {

// Items/subsequences
!cell: ex_atm_cell;

// The body() method


body() @driver.clock is {
var preprepared_cell: ex_atm_cell;

5-34 e Reuse Methodology


Sequences: Constructing Test Scenarios
Constraining Complex Sequence Items

gen preprepared_cell;
...
do cell keeping {it == preprepared_cell};
};
};

To return immediately (non-blocking do), implement the method that processes the item to be
non-time-consuming and return immediately.

5.8.5 Constraining Complex Sequence Items


Constrain complex sequence items when

Suppose you have a data item that contains a list with items that you want to constrain. In this case, you
cannot use the it variable to refer to the list items, because it already refers to the data item itself. Instead,
you must specify a new name for the list items. In the following example, the name “item” is used for
this purpose.
extend NEW my_sequence {
body @driver.clock is only {
do burst keeping {
.addr <= 1000;
.type in [READ, WRITE];
for each (data_item) in .data { // Specify name for list item
data_item > 10 and data_item < 90;
};
};
};
};

5.9 Implementing Complex Scenarios


This section contains:

• “Defining Concurrent Sequences” on page 5-36


• “Initializations and Configurations before Starting Sequences” on page 5-37
• “Interrupt Sequences” on page 5-37
• “Resetting and Rerunning Sequences” on page 5-39
• “DUT-Independent Read/Write Interface” on page 5-41
• “Controlling the Scheduling of Items” on page 5-43
• “Locking of Resources” on page 5-44

e Reuse Methodology 5-35


Sequences: Constructing Test Scenarios
Defining Concurrent Sequences

• “BFM-Driver Interaction Mode” on page 5-44

5.9.1 Defining Concurrent Sequences


You can create concurrent sequences in two ways:

• Using the do action within an all of block


• Starting several sequences using the start_sequence() method

Example 1 Using the do action


In this example, the number of sequences is determined statically.
// Do multiple SHORT_LONG sequences in parallel
extend ex_atm_sequence_kind: [PARALLEL_3];
extend PARALLEL_3 ex_atm_sequence {
!sl_seq: SHORT_LONG ex_atm_sequence;
body() @driver.clock is {
all of {
{do sl_seq keeping {.short_count == 1}};
{do sl_seq keeping {.short_count == 2}};
{do sl_seq keeping {.short_count == 3}};
};
};
};

Example 2 Starting several sequences in parallel


In this example, the PARALLEL_N sequence activates n sequences in parallel. It does not wait for the
sequences to complete, but immediately finishes after activating the sequences.
// Do multiple SHORT_LONG sequences in parallel
extend ex_atm_sequence_kind: [PARALLEL_N];
extend PARALLEL_N ex_atm_sequence {

// num_of_sequences can be constrained from above


num_of_sequences: int;
keep soft num_of_sequences == 3;
// The list of sequences to activate
sl_seq_l: list of SHORT_LONG ex_atm_sequence;
keep sl_seq_l.size() == num_of_sequences;
keep for each in sl_seq_l {
it.driver == driver;
};

5-36 e Reuse Methodology


Sequences: Constructing Test Scenarios
Initializations and Configurations before Starting Sequences

body() @driver.clock is {
for each (seq) in sl_seq_l {
it.start_sequence();
};
};
};
Note The number of sequences that PARALLEL_N activates can be controlled by a higher-level
sequence.

5.9.2 Initializations and Configurations before Starting


Sequences
The sequence driver generates the MAIN sequence and starts its body() method upon run(). Sometimes
you might want to perform some operations before starting to randomize the sequences. For example, a
test might start with a configuration stage and an initialization stage before the actual testing starts.

You can implement these preliminary stages of the test with sequences. For example:
extend MAIN ex_atm_sequence {
body() @driver.clock is only {
do initialization_sequence;
...
};
};

Another way to perform initializations before the test is by extending the pre_body() method to delay
the execution of body(). For example:
extend MAIN ex_atm_sequence {
pre_body() @sys.any is {
// Perform configuration
configure_dut();
// Wait until initialization is done
sync true(driver.initialization_done);
};
};

5.9.3 Interrupt Sequences


Many environments include an interrupt option. Typically, an interrupt occurrence should be coupled
with some reaction from the agent. Once the interrupt is done, you can consider either aborting any
previous activity or continuing it from the point where it stopped. All of this can be supported using
sequences.

e Reuse Methodology 5-37


Sequences: Constructing Test Scenarios
Interrupt Sequences

To handle interrupts using sequences:

1. Define an interrupt sequence that implements the reaction-upon-interrupt scenario, including:

a. Wait for the interrupt event to occur (that is, serves as the interrupt handler).

b. Grab the sequence driver for exclusive access.

c. (Optional) Stop the activity of the other existing sequences.

d. Execute the interrupt scenario.

e. Ungrab the sequence driver.

2. Instantiate the interrupt sequence under the sequence driver.

3. Start the interrupt sequence in the run() method of the sequence driver.

Example
(Taken from ex_interrupt_abort_test.e in the ex_atm/examples directory.)
// 1. Define an interrupt sequence.
extend ex_atm_sequence_kind: [INTERRUPT_ABORT];
extend INTERRUPT_ABORT ex_atm_sequence {
// Upon interrupt, grab driver, terminate all its main activity, and
// send a configuration sequence
body() @driver.clock is {
sync @driver.interrupt; // Wait for the interrupt event.
grab(driver); // Grab the driver.
driver.sequence.stop(); // Stop the MAIN sequence activity.
do cell keeping {.color == RED}; // Execute the interrupt scenario.
do cell keeping {.color == GREEN};
do cell keeping {.color == BLUE};
ungrab(driver); // Ungrab the driver.
};
};

extend ex_atm_driver {
// 2. Instantiate the interrupt sequence under the sequence driver
iseq: INTERRUPT_ABORT ex_atm_sequence;
keep iseq.driver == me;

// 3. Start the interrupt sequence


run() is also {
iseq.start_sequence();
};
};

5-38 e Reuse Methodology


Sequences: Constructing Test Scenarios
Resetting and Rerunning Sequences

// The test part


extend MAIN ex_atm_sequence {
keep count == 1;
keep sequence is a ALTERNATING_COLOR ex_atm_sequence;
};
Note You can make the activity-termination option a parameter of the interrupt sequence. For example,
you could have the sequence actually terminate the other activity only if a Boolean flag is set.

5.9.4 Resetting and Rerunning Sequences


Sometimes you might need to re-execute (reactivate) the sequence driver and its sequences. For
example, this could happen upon reset of the DUT.

All Specman structs have the predefined method rerun() for reactivating the struct and re-executing the
run() method.

There are two typical modes of operation upon reset:

• Call quit() upon reset. Then, at the end of the reset, call rerun().
• Call rerun() upon reset. Then use the reset-qualified clock for the struct’s TCM.
For sequence drivers, the following methods support re-execution of sequences:

driver.quit() Calls to quit() for every started sequence under the driver
driver.rerun() 1. Calls to quit()

2. Resets the runtime data of the driver

3. Resets the runtime data of all started sequences

4. Re-executes the run() method, which by default starts the MAIN sequence

Notes
• When calling to rerun(), the driver continues driving items until the end of the cycle. If the driver
was in the middle of do-ing an item at the end of the cycle, then that item might be lost.
• When you have a virtual sequence that controls multiple BFM sequence drivers, rerunning any of
the BFM sequence drivers does not terminate the virtual sequence. If the virtual sequence was in the
middle of do-ing a BFM sequence that was do-ing an item at the end of the cycle, then that item
might be lost but the BFM sequence continues.

The following runtime data is reset upon rerun, at the beginning of the next cycle:

e Reuse Methodology 5-39


Sequences: Constructing Test Scenarios
Resetting and Rerunning Sequences

All do item actions waiting This includes do actions initiated by a higher-level virtual sequence
to be performed that continues to run. In such case, those do item actions are skipped,
and the sequence continues to run.
grab() method If the driver was grabbed by a sequence before the reset, then the grab
will be canceled along with the entire queue of sequences waiting to
grab the driver. Therefore, a higher-level virtual sequence that
grabbed the driver before the reset must regrab it if needed.
Sequences that were waiting to grab the driver (that is, were blocked
in the grab() method) are released without grabbing the driver.
The list of previously sent You cannot use last() to retrieve items that were done before the
items rerun. For more information on last(), see “last()” on page 5-78.

Any additional actions needed at quit() time can be added to the quit() method of the driver using is
also. For example:
extend ex_atm_sequence_driver {
quit() is also {
out("quitting driver", me);
};
};

Any additional actions needed at rerun() time can be added to the rerun() method of the driver using is
also. For example:
extend ex_atm_sequence_driver {
rerun is also {
out("rerunning driver", me);
};
};

Sometimes, you might want to regenerate some of the driver’s data upon rerun() (before re-executing
the driver’s run()). You can do that by extending the method driver.regenerate_data(). For example:
extend ex_atm_sequence_driver {
regenerate_data() is also {
gen sequence;
};
};
Note The rerun() method performs the following operations:

• Quits the struct (which causes the termination of all TCMs and TEs).
• Executes the run() method.
• Re-initiates all TEs.

5-40 e Reuse Methodology


Sequences: Constructing Test Scenarios
DUT-Independent Read/Write Interface

5.9.5 DUT-Independent Read/Write Interface


The uniform interface of sequences lets you develop a generic read/write interface that might be applied
to many environments and is not related directly to a specific DUT. Such an interface enables
development of system-level tests that are suitable for many configurations of the environment.

A typical example is a bus-based configuration test that can be executed over multiple buses, for
example, a PCI bus as well as an ATM bus.

To implement a DUT-independent interface:

1. Define a virtual read/write sequence that uses a generic low-level sequence driver to execute the
low-level read/write transactions.

2. Hook the virtual sequence driver to a specific sequence driver as follows:

a. Instantiate the virtual sequence driver.

b. Connect its low-level sequence driver to a specific sequence driver.

c. Implement the read/write interface methods of the low-level sequence driver.

Note The last portion of the step (2c) might be done already as part of the specific
environment. See “Enhancing the User Interface” on page 5-17.

3. Use the virtual sequence driver in tests.

Note Each of these steps should reside in a separate file (to allow reuse).

Example
(This is from ex_cbus_rw_test.e in the ex_c_bus/examples directory.)

1. Define a virtual read/write sequence.


sequence config_sequence;
extend config_sequence_driver {
low_driver: any_sequence_driver;
event clock is only @sys.any;

// Implement the read/write interface so that it uses the low-level


// sequence driver interface.

write(address: list of bit, data: list of bit) @clock is {


low_driver.write(address, data);
};

read(address: list of bit) : list of bit @clock is {

e Reuse Methodology 5-41


Sequences: Constructing Test Scenarios
DUT-Independent Read/Write Interface

result = low_driver.read(address);
};
};

2. Hook up the virtual sequence driver.


extend sys {
cbus_env: c_bus_env is instance;

// Instantiate the virtual sequence driver.


config_driver: config_sequence_driver is instance;

// Connect its low-level sequence driver to a specific sequence


// driver.
keep config_driver.low_driver == cbus_env.driver;
};

// Implement the read/write interface methods of the low-level sequence


// driver.
extend ex_c_bus_driver {
write(address: list of bit, data: list of bit) @clock is {
sequence.write(pack(NULL, address), pack(NULL, data));
};

read(address: list of bit) : list of bit @clock is {


result = pack(NULL, sequence.read(pack(NULL, address)));
};
};

// Make the c_bus MAIN silent.


extend MAIN ex_c_bus_sequence {
keep count == 0;
};

3. Test Example: A generic (that is, DUT-independent) configuration test.


extend MAIN config_sequence {
!w_data: uint(bits:4);
!r_data: uint(bits:4);
!addr: uint(bits:6);

body() @driver.clock is only {


gen w_data;
gen addr;
outf("sending data: %d to address: %x\n", w_data, addr);
driver.write(%{addr},%{w_data});
r_data = %{driver.read(%{addr})};
outf("received data: %d from address: %x\n", r_data, addr);

5-42 e Reuse Methodology


Sequences: Constructing Test Scenarios
Controlling the Scheduling of Items

};
};

Notes
• The test itself has no notion of the actual agent that eventually executes the read/write transactions.
• A similar approach can be used to develop additional generic actions such as reset.
• The use of list of bit and packing in the read/write interface of the sequence driver is essential to
prevent dependency on a specific agent or format and a specific bit width.

5.9.6 Controlling the Scheduling of Items


There might be several sequences do-ing items concurrently, but the driver can only handle on item at a
time. So the driver maintains a queue of do actions; and when there is a demand for an item, the driver
chooses a single do action to perform from the do actions waiting in the queue. Therefore, when a
sequence is do-ing an item, the do action is blocked until the driver is ready to choose it.

The scheduling algorithm works on a first-come-first-served basis. You can change the algorithm using
grab() and is_relevant().

If a sequence is grabbing the driver, the driver will choose the first do action that satisfies the following
conditions:

• It is done by the grabbing sequence or its descendants.


• The is_relevant() method of the sequence do-ing it returns TRUE.
If no sequence is grabbing the driver, the driver will choose the first do action that satisfies the following
condition:

• The is_relevant() method of the sequence do-ing it returns TRUE.


If there is no do action to choose, then get_next_item() is blocked. The driver will try to choose again
(reactivate the scheduling algorithm) when one of the following happens:

• Another do action is added to the queue.


• A new sequence grabs the driver, or the current grabber ungrabs the driver.
• The method driver.check_is_relevant() is called. (For more information see “Forcing a Reevaluation
of the do Action Queue” on page 5-51.)

• A new cycle begins.


When calling to try_next_item(), if the driver does not succeed in choosing a do action before the time
specified by driver.wait_for_sequences() elapses, then try_next_item() returns anyway but with
NULL.

e Reuse Methodology 5-43


Sequences: Constructing Test Scenarios
Locking of Resources

To control scheduling:
• Use is_relevant() to specify a condition for performing a do action.
or

• Grab the driver.

5.9.7 Locking of Resources


Sometimes a sequence might need to lock resources for a while so that temporarily other sequences will
not be able to touch them.

For example, a divide-by-zero machine instruction sequence might look like this:
extend DVZ inst_sequence {
op1_reg: register;
op2_reg: register;

body() @driver.clock is {
do SET_REG inst_sequence keeping {.reg == op1_reg};
...Do any random sequence not writing to op1_reg
do SET_REG inst_sequence keeping {.reg == op2_reg; .value == 0};
...Do any random sequence not writing to op1_reg or op2_reg
do instr keeping {
.op == divide;
.op1 == op1_reg;
.op2 == op2_reg
};
...Release the locking on op1_reg and op2_reg
};
};

The question is what to put in the lines starting with the ellipsis “...”. grab() and ungrab() will not work
here. They are useful to grab sequence drivers, not registers.

Verisity recommends using either Boolean flags or lockers inside the sequence driver (or inside the unit
where the sequence driver resides). Have one flag or locker for every resource that you want to lock (for
example, a register that you do not want people to write to).

5.9.8 BFM-Driver Interaction Mode


“Hooking the Sequence Driver to the Environment” on page 5-9 describes how to hook the sequence
driver into the environment. In the example given, there is a TCM in the BFM that explicitly calls to
driver.get_next_item() in order to receive an item. This means that the environment controls when to
get an item from sequences. This style of interaction is called PULL_MODE. It is the default mode.

5-44 e Reuse Methodology


Sequences: Constructing Test Scenarios
BFM-Driver Interaction Mode

Sometimes you might want the sequences to be the initiators so that you do not need to request an item.
Instead, when the driver is ready to do an item, there is an implicit call to driver.send_to_bfm(). This
style of interaction is called PUSH_MODE.

The interaction mode is determined by the value of driver.bfm_interaction_mode, which is constrained


by default to PULL_MODE.

5.9.8.1 Working in PUSH_MODE


To work in PUSH_MODE:

1. Constrain driver.bfm_interaction_mode to be PUSH_MODE.

2. Implement the driver.send_to_bfm() TCM so that it calls the BFM TCM that drives the item into
the DUT.

Table 5-1 PULL_MODE versus PUSH_MODE Example

PULL_MODE PUSH_MODE
extend ex_atm_bfm { extend ex_atm_driver {
execute_items() @clock is { // Set interaction mode
var seq_item: ex_atm_cell; keep bfm_interaction_mode ==
while TRUE { PUSH_MODE;
seq_item = // Transfer the item from the
driver.get_next_item(); // driver to the BFM:
drive_cell(seq_item); // Add a call to the BFM's TCM in
emit driver.item_done; // the sequence driver's
}; // send_to_bfm()
}; send_to_bfm(seq_item: ex_atm_cell)
@clock is only {
run() is also { bfm.drive_cell(seq_item);
start execute_items(); };
}; };
};

Notes
• In PUSH_MODE, driver.item_done is automatically emitted when driver.send_to_bfm() returns.
• PUSH_MODE is implemented using PULL_MODE in the following way:
send_loop() @clock is {
while TRUE {
var seq_item := get_next_item();
send_to_bfm(seq_item);
emit item_done;

e Reuse Methodology 5-45


Sequences: Constructing Test Scenarios
Miscellaneous Advanced Features

};
};

• The BFM interaction mode is a static property of the environment. It must not be modified during
simulation.

For more information about the difference between PUSH_MODE and PULL_MODE, compare Figure
5-11 on page 5-94 to Figure 5-12 on page 5-95.

5.10 Miscellaneous Advanced Features


This section includes:

• “Disabling Automatic Launch of the MAIN Sequence” on page 5-46


• “Creating a Common Base for Your Sequences and Sequence Drivers” on page 5-46
• “Applying Default Behavior When No Item Is Done” on page 5-48
• “Synchronization within a Cycle” on page 5-49
• “Quitting Sequences and Sequences Items” on page 5-52

5.10.1 Disabling Automatic Launch of the MAIN Sequence


Normally, the MAIN sequence is generated and started automatically upon driver.run(). However, you
can disable this automatic process.

To disable automatic generation and launching of the MAIN sequence:


• Constrain the gen_and_start_main field under the sequence driver to be FALSE.
For example:
extend ex_atm_driver {
keep soft gen_and_start_main == FALSE;
};

5.10.2 Creating a Common Base for Your Sequences and


Sequence Drivers
A typical environment contains several sequences that use different items and also virtual sequences.
For example:
sequence atm_sequence using item=atm_cell;
sequence ethernet_sequence using item=ethernet_packet;

5-46 e Reuse Methodology


Sequences: Constructing Test Scenarios
Creating a Common Base for Your Sequences and Sequence Drivers

sequence comm_sequence;

Although atm_sequence, ethernet_sequence, and comm_sequence are different sequence families, they
can have a common logic and functionality. Therefore, you might want to define a common base for
your sequences and a common base for your drivers. Some times when this could be useful are:

• When using layered sequence drivers that have a common functionality (for example, in the way
they extract data from the higher-level driver)
• When you want each sequence to print a standard header or footer when it is started or ended
• When you want to associate different sequences or drivers that use different items in one logic family,
(for example, all AHB sequences)

This section includes:

• “Creating a Common Base for Your Sequences” on page 5-47


• “Creating a Common Base for Your Sequence Drivers” on page 5-48

5.10.2.1 Creating a Common Base for Your Sequences


To create a common base for your sequences:

1. Define a base_sequence struct that inherits from any_sequence (directly or indirectly).


struct base_sequence like any_sequence {

2. Implement the common logic for your sequences in your base_sequence struct.

3. Add the option sequence_type=base_sequence to the sequence statement for each sequence struct
that you want to inherit from base_sequence.

For example:
sequence my_seq using item=my_item, sequence_type=base_sequence;
Specifying sequence_type causes newly created sequence structs to inherit from base_sequence
rather than any_sequence.

Notes
• The base_sequence struct can be derived from another base_sequence struct, not only from
any_sequence.
• The base_sequence struct only establishes a common logic. You cannot instantiate or generate an
instance of this type.

e Reuse Methodology 5-47


Sequences: Constructing Test Scenarios
Applying Default Behavior When No Item Is Done

5.10.2.2 Creating a Common Base for Your Sequence Drivers


To create a common base for your sequence drivers:

1. Define a base_sequence_driver unit that inherits from any_sequence_driver (directly or


indirectly).
struct base_sequence_driver like any_sequence_driver {

2. Implement the common logic for your sequence drivers in your base_sequence_driver unit.

3. Add the option sequence_driver_type=base_sequence_driver to the sequence statement for each


sequence with a sequence driver that inherits from base_sequence_driver.

For example:
sequence my_seq using item=my_item,
sequence_driver_type=base_sequence_driver;
Specifying sequence_driver_type causes newly created sequence drivers to inherit from
base_sequence_driver rather than any_sequence_driver.

Notes
• The base_sequence_driver unit can be derived from another base_sequence_driver unit, not only
from any_sequence_driver.
• The base_sequence_driver only establishes a common logic. You cannot instantiate or generate an
instance of this type.

5.10.3 Applying Default Behavior When No Item Is Done


Some designs require the BFM to perform activity under any circumstances. For example, some buses
require a continuous transmission of data, even if it is an idle data. For such designs, using the normal
hookup scheme cannot suffice; because in those schemes, if there is no valid do action at the moment,
the sequences block any BFM activity. In other words, the return of get_next_item() is blocked until a
valid do action exists.

To solve such cases, you can use the try_next_item() TCM:


any_sequence_driver.try_next_item(): seq_item @clock;

This TCM tries to return the current item being done by the sequences. However, unlike
get_next_item(), if no such item exists, it returns NULL in the same cycle that it is called. This lets the
user create a default item instead of the item that was supposed to be created by the sequences, thereby
adhering to the DUT rules.

5-48 e Reuse Methodology


Sequences: Constructing Test Scenarios
Synchronization within a Cycle

Note try_next_item() does not just look for an existing candidate for a do but also allows sequences
to execute their body() TCMs and then look for a possible do action. This is done by calling the
wait_for_sequences() TCM (see “Solving Possible Race Conditions” on page 5-50).

To apply default behavior when no item is currently created by the sequences:

1. Replace the call to driver.get_next_item() (as demonstrated in Step 4 of the hookup scheme in
“Hooking the Sequence Driver to the Environment” on page 5-9) with a call to the try_next_item()
TCM.

Note This method must be used in PULL_MODE only.

2. When try_next_item() returns NULL, explicitly create your item instead.

Example:
extend ex_atm_bfm {
pull_send_loop() @clock is only {
var seq_item: ex_atm_cell;
while TRUE {
seq_item = driver.try_next_item();
if seq_item == NULL {
seq_item = new;
};
drive_cell(seq_item);
emit driver.item_done;
};
};
};

See Also
• Figure 5-13 on page 5-96
• Figure 5-12 on page 5-95

5.10.4 Synchronization within a Cycle


This section contains:

• “Delaying the Driver Clock” on page 5-50


• “Solving Possible Race Conditions” on page 5-50
• “Forcing a Reevaluation of the do Action Queue” on page 5-51

e Reuse Methodology 5-49


Sequences: Constructing Test Scenarios
Synchronization within a Cycle

5.10.4.1 Delaying the Driver Clock


Sometimes you must let the environment execute before the sequences execute. A typical example is
when a BFM must export its status before sequences are evaluated so that they can use the new status to
generate updated data.

To enable an intracycle delay (a delay within the same cycle) of sequence activity:
• Use the delay_clock() TCM.
any_sequence_driver.delay_clock() @sys.any;

After an intracycle delay, the delay_clock() TCM emits the driver’s clock just once.

To delay the driver clock:

1. Remove any connection to the driver clock (see the hookup scheme in “Hooking the Sequence Driver
to the Environment” on page 5-9).

2. Define a TCM that calls to driver.delay_clock() every cycle.

For example:
extend ex_atm_bfm {
delay_driver_clock() @a_clock is {
while TRUE {
// Emit the driver.clock after some delay
driver.delay_clock();
wait cycle;
};
};
run() is also {
start delay_driver_clock();
};
};
Note This TCM replaces the regular clock connection, so make sure that the clock is not also
emitted.

5.10.4.2 Solving Possible Race Conditions


In complicated environments (for example multilayer environments), a race condition might occur
between parallel threads of TCMs. For example, this could occur between layered BFMs or between the
BFM and the sequence driver.

A typical case is when one thread produces some data that another thread consumes. If the consumer is
evaluated before the producer, it could happen that the consumer will be called first and will miss the
producer, even though both occurred in the same cycle.

5-50 e Reuse Methodology


Sequences: Constructing Test Scenarios
Synchronization within a Cycle

Solving such cases can be done by explicitly performing a context switch in the consumer that lets the
producer be evaluated first.

To perform a context switch that forces a producer to be evaluated before a consumer:


• Use the wait_for_sequences() TCM:
For example:
any_sequence_driver.wait_for_sequences() @sys.any;

This TCM can be called by the consumer before or in parallel with waiting for the producer. This TCM
does not exceed the boundary of the cycle but uses time-consuming actions such as sync [0] to create an
artificial context switch.

This TCM is already used in the sequence mechanism in the call to try_next_item(). try_next_item()
calls wait_for_sequences() to allow evaluation of the sequences before looking for existing do actions.

You can also extend or override this TCM if the existing implementation does not satisfy the needs of
your environment. For example:
extend ex_atm_driver {
wait_for_sequences() @sys.any is only {
for i from 1 to 100 {
sync [0];
};
};
};
Note Overriding wait_for_sequences() also affects the behavior of try_next_item().

5.10.4.3 Forcing a Reevaluation of the do Action Queue


When there is a demand for items, the driver chooses a do action only if the is_relevant() method of the
sequence returns TRUE. But the returned value of is_relevant() might depend on the current state of the
environment. In that case, the driver might fail to choose a do action when the sampling time of
is_relevant() is prior to the changes in the env. In that case, you can force a reevaluation of the do action
queue.

To force a reevaluation of the do action queue:


• Call the method driver.check_is_relevant().
Note This check_is_relevant() method is meaningful only for synchronization within a cycle. When
a new cycle starts, the driver automatically reevaluates the queue.

e Reuse Methodology 5-51


Sequences: Constructing Test Scenarios
Quitting Sequences and Sequences Items

5.10.5 Quitting Sequences and Sequences Items


Specman Elite continues evaluating temporal expressions until quit() is called. Garbage collection for a
struct only occurs after Specman Elite stops evaluating the struct’s temporal expressions. This also
applies for sequences and sequence items. Therefore, if you use temporal expressions in a sequence or
sequence item, quit() must be called before Specman Elite can perform garbage collection on the
sequence or sequence item.

To enable automatic quitting of sequences and sequence items:


• Set the predefined method any_sequence_item.auto_quit() to TRUE.
extend any_sequence_item {
auto_quit() : bool is only {
return TRUE;
};
};
When auto_quit() returns TRUE, quit() is automatically called for sequences after the sequence is
finished and for sequence items after driver.item_done is emitted.

Note By default, auto_quit() currently returns FALSE. In future, the default will change to TRUE.

You can override the setting of auto_quit() for specific types.

To override the auto_quit() setting:


• Extend the relevant sequence or sequence item type.
For example:
extend my_sequence_item {
auto_quit() : bool is only {
return FALSE;
};
};

5.11 Layering of Protocols


This section discusses the layering of protocols and how to implement it using sequences.

This section includes:

• “Introduction to Layering” on page 5-53


• “Styles of Layering” on page 5-56
• “Using Layered Sequence Drivers” on page 5-60

5-52 e Reuse Methodology


Sequences: Constructing Test Scenarios
Introduction to Layering

5.11.1 Introduction to Layering


Simple eVCs and VEs might not need layering of protocols, but in complex situations it is often
required. Two examples are TCP/IP over Ethernet and ATM over Sonet.

Sequence layering and virtual sequences are the two main ways in which sequence drivers can be
composed to create a bigger whole.

In the erm_lib directory, there are two example packages that demonstrate layering:

ex_blayers This eRM package (basic layers) demonstrates a simple layering configuration.
It shows a low-layer packet sequence driver that can either work alone or pull
information from a high-layer frame sequence driver. (For details, see the
PACKAGE_README.txt of the package.)
ex_layers This eRM package demonstrates the use of multiple high- and low-layer
sequence drivers as well as virtual sequence drivers, all interacting in the
layering scheme. It also demonstrates late binding of the various layers
(emulating a situation where different people wrote separate eVCs that are later
bound together by yet another person). (For details, see the
PACKAGE_README.txt of the package.)

This section includes:

• “What Is Layering of Protocols?” on page 5-53


• “Layering and Sequences” on page 5-54

5.11.1.1 What Is Layering of Protocols?


The classic example is where the don't-care data (just a list of byte) in the lower-level protocol suddenly
is forced by the higher-level protocol to be meaningful.

For example, assume that there are two sequence drivers. The low-layer sequence driver drives packets
that are defined as:
struct packet like any_sequence_item {
data[10]: list of byte;
... -- Other fields
};

So the low-level sequence driver is defined as:


sequence packet_sequence using item = packet;

e Reuse Methodology 5-53


Sequences: Constructing Test Scenarios
Introduction to Layering

In one case, you just want to send packets with random data. In another case, you want the data to come
from a higher-layer data protocol. The higher-layer protocol in the example drives frames. So the
high-level sequence driver is defined as:
sequence frame_sequence using item = frame;

A frame would then have various fields that must be packed together and sent in the data lists of n
consecutive packets.

5.11.1.2 Layering and Sequences


Layering is best implemented in e via sequences. There are two main ways to do layering using
sequences:

• “Layering Inside One Sequence Driver” Applies for simple cases only
• “Layering of Several Sequence Drivers” Applies for all layering needs

Layering Inside One Sequence Driver


In this case, you simply generate a data item of the higher layer within the lower-layer sequence. You do
that by inventing another sequence kind for the lower-layer sequence driver. For example:
extend packet_sequence_kind: [FRAME_SENDER];

The FRAME_SENDER sequence generates a single frame and sends it in chunks, in one or more
packets, until the data of the frame is exhausted. For example:
extend FRAME_SENDER packet_sequence {
frame: frame;
!packet: packet;

body() @driver.clock is {
var full_data: list of byte = pack_the_frame(); // Pack the frame

while not done_with_full_data() { // while not done with full_data


var next_piece: list of byte=get_next_chunk_from_full_data();
do packet keeping {.data == next_piece};
};
};
};

The FRAME_SENDER sequence can then be used by other sequences. For example, you could define a
SUPER_FRAME_SENDER packet_sequence that takes a super_frame (whatever that is), chops it into
frames, and executes in a loop as follows:
do FRAME_SENDER sequence keeping {

5-54 e Reuse Methodology


Sequences: Constructing Test Scenarios
Introduction to Layering

.frame == get_next_frame_in_super_frame();
};

Layering inside one sequence driver is easy to write and understand. However, it only works well in
simple cases. For complex cases, you need a more general approach.

Layering of Several Sequence Drivers

Figure 5-4 Layering Architecture


Single-Layer
Packet SD
Architecture seq
seq
seq

Packet BFM

DUT

Multi-Layer
Frame SD
Architecture seq
seq
seq

Packet SD
seq
seq This packet sequence
seq
pulls information
directly from the Frame
Packet BFM sequence driver.

DUT

The more general approach uses multiple sequence drivers (see Figure 5-4 on page 5-55).

Taking the frame and packet example, there would be a low-layer packet_sequence and a high-layer
frame_sequence (complete with their sequence drivers). The packet_sequence would pull data from the
frame_sequence_driver (or from its BFM).

Each sequence driver might even be encapsulated in an eVC so that layering could be done by
connecting the eVCs.

For more information, see “Using Layered Sequence Drivers” on page 5-60.

e Reuse Methodology 5-55


Sequences: Constructing Test Scenarios
Styles of Layering

5.11.2 Styles of Layering


This section includes:

• “Basic Layering” on page 5-56


• “One-to-One, One-to-Many, Many-to-One, Many-to-Many” on page 5-57
• “Different Configurations at Pre-Run Generation and Runtime” on page 5-58
• “Timing Control” on page 5-58
• “Data Control” on page 5-58
• “Complex Inter-Packet Dependencies” on page 5-59
• “Using Virtual Sequence Drivers” on page 5-59

5.11.2.1 Basic Layering


The simplest general scenario is:

• The actual BFM accepts layer1 packets.


• The layer1 packets are constructed out of layer2 packets in some way, the layer2 packets are in turn
constructed out of layer3 packets, and so on.
• Between every layerN and layerN+1, there is a mechanism that takes layerN+1 packets and converts
them into layerN packets.

You could also have multiple kinds of layer1 and layer2 packets (as in Figure 5-5 on page 5-57). In
different configurations you might want to layer any kind of layer2 packet over any kind of layer1
packet.

The rest of this section describes some possible variations and complications, depending on the
particular protocol or on the desired test-writing flexibility.

5-56 e Reuse Methodology


Sequences: Constructing Test Scenarios
Styles of Layering

Figure 5-5 Layering of Protocols


Kinds:
RAW
LAYER2A
LAYER2B

Layer 1a header kind Payload (32 bytes) CRC

Layer 1b header kind Payload (64 bytes) CRC

Layer 2a address Payload (31 bytes)


1 byte

Layer 2b address length Payload (1..100 bytes)


1 byte 1 byte

5.11.2.2 One-to-One, One-to-Many, Many-to-One, Many-to-Many


Figure 5-6 Layer Mapping
One to One
Layer 2a address Payload (31 bytes)
2A
Layer 1a header kind Payload (32 bytes) CRC

Many to One
Layer 2a address Payload (31 bytes)
2A
Layer 1b header kind Payload (64 bytes) CRC

Many to Many
add len Payload (20 bytes) add len Payload (20 bytes) add len Payload (18 bytes)
2B
header
head kind Payload (32 bytes) CRC header kind Payload (32 bytes) CRC

The conversion mechanism might need to cope with any of the following situations:

e Reuse Methodology 5-57


Sequences: Constructing Test Scenarios
Styles of Layering

One-to One One high-layer packet must be converted into one low-layer packet.
One-to-Many One big high-layer packet must be broken into many low-layer packets.
Many-to-One Many high-layer packets must be combined into one big low-layer packet
(as in Sonet).
Many-to-Many Multiple higher-layer packets must be taken in and converted into multiple
lower-layer packets. For example, high-layer packets are 10 bytes long, and
low-layer packets are 3 to 35 bytes long. In this case, there could be
remainders.

5.11.2.3 Different Configurations at Pre-Run Generation and Runtime


You might want to build different configurations—either by loading different files or by randomizing
something during pre-run generation.

For example, in one configuration, you might have only layer1 packets. In another configuration, layer1
packets would be dictated by layer2 packets. You might also want to decouple the layers further, for
example, so that layer2 packets could drive either layer1 packets or layer1 cells (at another interface) or
both.

The general picture here is boxes with connecting pipes. At pre-run generation, you can connect the
pipes according to the required configuration or topology.

Sometimes, you might want to decide on the mix of input from multiple sources at runtime. For
example, you might want to have one low-layer sequence driver send n packets that come from one
high-layer sequence driver and then m packets from another high-layer sequence driver.

5.11.2.4 Timing Control


In some configurations, the high-layer packets drive the timing completely. When high-layer packets are
created, they are immediately converted into low-layer packets.

In other configurations, the low-layer sequences pace the operation. When a low-layer do is executed,
the corresponding high-layer packet should appear in zero time, much like with reactive sequences.

Finally, there is a case where things are driven into the DUT according to the timing of the low-layer
sequences, but the high-layer sequences are not reacting in zero time. Rather, if there is no data available
from the high-layer sequences, then some default value (for example, a zero filler) is used instead.

5.11.2.5 Data Control


In some configurations, the high-layer transactions completely dictate what low-layer items reach the
DUT. The low layer simply acts as a slave.

5-58 e Reuse Methodology


Sequences: Constructing Test Scenarios
Styles of Layering

Often, however, both layers influence what reaches the DUT. For example, the high layer might
influence the data in the payload while the low layer influences other attributes of the items reaching the
DUT. As such, the choice of sequences for both layers is meaningful.

5.11.2.6 Complex Inter-Packet Dependencies


In some cases, complex transformations must be performed. Just shoving data from the high layer to the
low layer will not suffice. For example:

Serial number handling Assume that each packet has serial numbers, and serial numbers
should be given using some global algorithm that takes into
account all high-layer requests.
Retransmit handling Assume that this is a two-way protocol. The other side can send
back ACK and NACK (acknowledge and not acknowledge)
packets, and the high-layer protocol must retransmit some packets
accordingly. At the same time, you might already be outside the
high-layer request that created the original packet for which a
NACK was received.
Complex blocking issues Assume that a given low-layer sequence driver is sending packets
from one high-layer source that drives a high-layer transaction to
one target (slave). Assume also that the target cannot receive
packets for other high-layer transactions; however, other targets
can. Thus, the given low-layer sequence driver can process
multiple high-layer transactions at the same time, as long as you do
the necessary queueing so that any subsequent high-layer
transactions to the same slave wait for their turn in the correct
queue.

One thing common to all of these examples is the need for some global information (the counter in the
first example and the queue in the last example) and some corresponding global control.

5.11.2.7 Using Virtual Sequence Drivers


In the most general case, you have a graph consisting of several virtual sequence drivers and several
BFM sequence drivers. Some low-layer BFM sequence drivers are connected to the DUT, some
higher-layer BFM sequence drivers are layered above them, and some virtual sequence drivers on top
feed into all of the BFM sequence drivers below.

In the example configuration shown in Figure 5-7 on page 5-60, a low-layer sequence driver (L1B) gets
input from multiple high-layer sequence drivers (two instances of L2A) as well as from a virtual
sequence driver.

e Reuse Methodology 5-59


Sequences: Constructing Test Scenarios
Using Layered Sequence Drivers

Figure 5-7 Most General Case—Using Virtual Sequence Drivers

Layering with virtual sequences Virtual SD


seq
Layering with connector sequences seq
seq

L2B SD
seq
seq
seq
L2A SD L2A SD L2A SD
seq seq seq
seq seq seq
seq L2B BFM seq seq

L1A SD L1B SD
seq seq
seq seq
seq seq

L1A BFM L1B BFM

DUT

5.11.3 Using Layered Sequence Drivers


The general solution for layering involves multiple, layered sequence drivers.

Assume that at the low layer you have a packet_sequence (and a packet_sequence_driver), and above it
you have a frame_sequence (and a frame_sequence_driver). Packets can either be layered (that is, their
payload contains data from frames) or independent (that is, their payload is random). (See Figure 5-4 on
page 5-55.)

This section includes:

• “Overview of the Layering Solution” on page 5-60


• “Introducing Layering into the Low-Layer Sequence” on page 5-62
• “Late Binding” on page 5-64

5.11.3.1 Overview of the Layering Solution


Layered sequence drivers work as follows:

• Lowest-layer sequence drivers send information to a real BFM (which typically toggles actual DUT
signals).

5-60 e Reuse Methodology


Sequences: Constructing Test Scenarios
Using Layered Sequence Drivers

• Higher-layer sequence drivers only send information to lower-layer sequence drivers. They may or
may not have their own BFMs, depending on whether complex transformations are needed from the
higher layer to the lower layer.
• Lower-layer drivers point to the higher-layer driver(s) from which information must be pulled (using
get_next_item() / try_next_item() or some connector method). The actual pointer configuration is
normally decided during pre-run generation.
The pulled information (either the higher-layer data or some transformation thereof) is put in a field
of the sequence and is then used to constrain various fields in the lower-layer item(s).

Following is an example of a connector packet sequence that pulls a single frame from the frame
sequence driver and then sends it as packets:
extend FRAME_SENDER packet_sequence {
!frame: frame;
!packet: packet;

body() @driver.clock is {
-- Get the frame from the frame_driver
frame = frame_driver.get_next_item();
emit frame_driver.item_done;
var full_data: list of byte = pack_the_frame();

while not done_with_full_data() {


var next_piece: list of byte =
get_next_chunk_from_full_data();
do packet keeping {.data == next_piece};
};
};
};
Note This simple example is very similar to the one in “Layering and Sequences” on page 5-54. But
there the frame was generated in the packet_sequence, and here it is pulled from the frame sequence
driver.

There are several ways to get information from a higher layer:

• You can get information from the higher layer by calling frame_driver.get_next_item() directly and
getting a frame (as was done in the single-item connector example above):
frame = frame_driver.get_next_item();

• You can call a method of the higher-layer BFM, not a method of the higher-layer sequence driver.
For example, you might want the BFM to do some transformations on the higher-layer data, returning
a list of bytes somehow extracted from it. For example:
raw_data = frame_bfm.get_data();

e Reuse Methodology 5-61


Sequences: Constructing Test Scenarios
Using Layered Sequence Drivers

Note The BFM is called here in PULL_MODE. It would probably use get_next_item() to get the
data from the higher-layer sequence driver, also in PULL_MODE. (See Figure 5-8 on page 5-62.)

• You can call some intermediate connector method in the lower-layer sequence driver, which will
later be extended (see “Late Binding” on page 5-64). For example:
raw_data = driver.get_payload();

Figure 5-8 Pulling Information from a High-Level BFM

Frame SD
seq
seq
seq To achieve complex data
transformation, we need a
BFM or a third-party
Frame BFM
transformer unit.

Packet SD
seq
seq
seq This sequence pulls
from the Frame BFM.

Packet BFM

DUT

5.11.3.2 Introducing Layering into the Low-Layer Sequence


This section explains the three main ways to introduce layering into the low-layer sequence so that it
will be able to pull information from above and use it:

• “Using a Single-Item Connector Sequence”


• “Using Implicit Connection (by Extending the Low-Layer Sequence)”
• “Using a Protocol-Aware Multi-Item Connector Sequence”
Your needs will determine which way is best for you.

Using a Single-Item Connector Sequence


Sometimes, you want to freely mix layered packets (packets whose payload comes from frames) with
independent packets.

5-62 e Reuse Methodology


Sequences: Constructing Test Scenarios
Using Layered Sequence Drivers

To allow for single-item granularity, you can use a single-item connector sequence, as demonstrated in
“Overview of the Layering Solution” on page 5-60. The sequence takes a single high-layer item (frame in
the example) and produces one or more low-layer items (packets in the example).

Using Implicit Connection (by Extending the Low-Layer Sequence)


Another situation is where you initially have a whole library of lower-layer sequences. Suddenly, you
want all lower-layer data items in all sequences to be layered.

To do that, you can extend the basic, low-layer sequence (rather than a specific CONNECTOR
sequence) and pull the information from above using the pre_do() method. This lets you avoid changing
the original body() method (which was customized for each sequence in the library).

Following is an example of implicit connection by extending a low-layer sequence:


extend packet_sequence {
use_layering: bool;
keep soft use_layering == FALSE;
keep in_seqence(packet_sequence) (p) =>
soft use_layering == p.use_layering;
!raw_data: list of byte;

pre_do(is_item: bool) @driver.clock is {


if is_item and use_layering then {
raw_data = frame_bfm.get_data();
-- Here you get the information from the frame BFM, not from the
-- frame sequence driver just to demonstrate this possibility.
};
};
};

extend packet {
keep in_sequence(packet_sequence) (p) and p.use_layering =>
data == p.raw_data;
};

Loading the above code and constraining use_layering to TRUE makes that sequence (and sequences
underneath it) use layering:
extend MAIN packet_sequence {
keep use_layering == TRUE;
};
Note This allows conditional layering. If that is not needed, you can remove the use_layering flag and
the logic around it.

e Reuse Methodology 5-63


Sequences: Constructing Test Scenarios
Using Layered Sequence Drivers

Using a Protocol-Aware Multi-Item Connector Sequence


Finally, there are cases where, in layered mode, the full low-layer sequence is (almost) completely
determined by the protocol.

Quite often, there is no way to mix layered and independent data items without breaking the protocol
and causing the DUT to go into an error state.

For example, the protocol might involve complex retransmit and blocking rules (see “Complex
Inter-Packet Dependencies” on page 5-59). The logic for these rules could either be embedded in the
BFM of the high-layer sequence driver (in which case the low-layer sequence is relatively free from
restrictions) or embedded in the low-layer sequence (in which case it becomes protocol-aware and has
very little freedom).

A protocol-aware sequence is typically a multiple data-item sequence (quite often lasting throughout the
test). Generally, it pulls the full high-layer item (frame in the example) as is from the layer above, adding
it to some global list (in the sequence itself or in the sequence driver). It then starts to create low-level
data items as needed. As required (for example, upon a NACK), it would consult the global list and other
global fields and do the appropriate thing (for example, retransmit some packets).

While this sounds like one, monolithic sequence, it might still have some degree of freedom (perhaps
freedom in timing or various ways to respond to a NACK). These should be encoded as generatable
fields in the sequence (and its subsequences), which could be constrained from outside.

5.11.3.3 Late Binding


Sometimes several people (or groups of people) can be involved in the development of layers. There are
several possibilities regarding how many persons are involved in the development and the role that each
person plays. In addition, there is the test writer, who uses constraints to define the actual configuration
of sequence drivers (and many other things).

One Person
Sometimes, the same party two layers and the connection between them are written together. This
typically occurs when the two layers always go together.

Two Persons
In some cases, the lower layer was written by a person with no knowledge of layering. Thereafter, the
higher layer is written by another person specifically for that lower layer. In this case (as in the previous
one), this strong coupling makes it possible to customize the BFM of the higher layer as needed to match
the low layer.

This is demonstrated in the ex_blayers example package.

5-64 e Reuse Methodology


Sequences: Constructing Test Scenarios
Using Layered Sequence Drivers

Three Persons
In this case:

• Person A writes the lower-layer part (item, sequence, sequence driver, BFM).
• Person B writes the higher-layer part (item, sequence, sequence driver).
A and B do not know about each other and might even ignore the need for layering.
• Person C connects the two by writing the connector sequence(s) and the rest of the connecting code.

Four Persons
This more general case is the one implemented in the ex_layers package. It goes as follows:

• Persons A and B are as in the three-persons case.


• Person C defines some empty connector methods in the lower-layer driver and then writes the
connector sequences that call those methods to pull in the information.
• Finally, person D defines how to pull information from any particular higher-layer source by
extending the connector methods in the lower-layer driver.

This more flexible scheme allows for the case where each lower-layer sequence driver has multiple
connector-unit references that are only wired at configuration time. Thus, a particular sequence (written
by person C or by the test writer) could take raw data from one connector unit and then some more data
from a second connector unit without caring whether the two connector units are of the same type or not.

Example

1. Define a generic list of connector units and the empty connector methods (get_payload(),
get_kind()), which initially just issue an error.

Note At this point this is not associated with any specific higher layer.
extend ex_layer1a_driver_u {

connectors : list of any_unit;


keep soft connectors.size() == 0;

get_payload(connector : any_unit) : list of byte @sys.any is {


error("Unrecognized/NULL connector unit in get_payload()");
}; -- get_payload()
}; -- extend ex_layer1a_driver_u

2. Define a sequence kind that pulls in a payload and a kind from a (yet unspecified) higher-level
sequence driver (or BFM) and stuffs it into a packet.

e Reuse Methodology 5-65


Sequences: Constructing Test Scenarios
Using Layered Sequence Drivers

extend CONNECTOR ex_layer1a_sequence {


connector: any_unit;
keep connector in driver.connectors; // Defined in Part 1

-- This is raw data coming from the higher layer protocol.


!raw_data : list of byte;

-- This is the Layer1a kind field coming from the higher-level


-- protocol.
!packet_kind : ex_layer1a_packet_kind_t;

-- Before do-ing items, grab the required data from the higher-layer
-- protocol by calling empty connector methods defined in the driver
-- (defined in Part 1).
pre_do(is_item : bool) @sys.any is also {
if is_item {
raw_data = driver.get_payload(connector);
packet_kind = driver.get_kind(connector);
};
}; // pre_do()

body() @driver.clock is only {


do packet keeping {
it.kind == packet_kind;
it.payload == raw_data;
};
}; // body()
}; // extend CONNECTOR ex_layer1a_sequence

3. In a separate file, specify how to connect layer1a to a specific higher-level driver (layer2a), by
extending get_payload().
extend ex_layer1a_driver_u {
get_payload(connector : any_unit) : list of byte @sys.any is first {
if connector is a ex_layer2a_driver_u (p) {
var packet := p.try_next_item();
if packet != NULL { // Has a real packet
emit p.item_done;
return pack(packing.low, packet);
} else { // No real packet. Therefore, return a filler
result.resize(32);
return result;
};
};
}; -- get_payload()
};

5-66 e Reuse Methodology


Sequences: Constructing Test Scenarios
Tracing and Debugging Sequences

5.12 Tracing and Debugging Sequences


This section describes the commands that enable tracing and debugging of sequences and sequence
drivers:

trace sequence on page 5-67 For runtime tracing of the creation of sequences and items
wave sequence on page 5-70 For runtime tracing of the items sent by the sequence driver in the
waveform viewer
show sequence on page 5-70 For postmortem analysis of specific sequence drivers

These three commands display information on sequences and items using the nice_string() method. For
information on the default and customized output of nice_string(), see “Customizing Display of Trace
and Debug Output” on page 5-71.

5.12.1 trace sequence

Syntax
trace seq[uence] [on | log_only | off]

Description
The trace sequence command turns On/Log Only/Off the trace flags inside the sequence drivers. When
the trace flag is On or Log Only, this causes each subsequence and item to be added to a trace list within
the corresponding sequence driver, to be use1d by show sequence.

When the trace is On, the information is displayed on the screen immediately.

Following is a sample trace sequence output:


Starting the test ...
Opening file for debug: atm.elog
Running the test ...
[0] ATM 1: SEQ(0) Starting MAIN ex_atm_sequence-@2
[0] ATM 1: SEQ(1) PARALLEL_3 ex_atm_sequence-@3 created
[0] ATM 1: SEQ(2) SHORT_LONG ex_atm_sequence-@4 created
[0] ATM 1: SEQ(2) SHORT_LONG ex_atm_sequence-@5 created
[0] ATM 1: SEQ(2) SHORT_LONG ex_atm_sequence-@6 created
[0] ATM 1: SEQ(3) ex_atm_cell-@7 (A1 GREEN 2) created
[3] ATM 1: SEQ(3) ex_atm_cell-@7 (A1 GREEN 2) sent by drvr 0

1.

e Reuse Methodology 5-67


Sequences: Constructing Test Scenarios
trace sequence

[3] ATM 1: SEQ(3) ex_atm_cell-@8 (A1 BLUE 2) created


[6] ATM 1: SEQ(3) ex_atm_cell-@8 (A1 BLUE 2) sent by drvr 0
[6] ATM 1: SEQ(3) ex_atm_cell-@9 (A1 GREEN 1) created
[8] ATM 1: SEQ(3) ex_atm_cell-@9 (A1 GREEN 1) sent by drvr 0
[8] ATM 1: SEQ(3) ex_atm_cell-@10 (A3 RED 1) created
[10] ATM 1: SEQ(3) ex_atm_cell-@10 (A3 RED 1) sent by drvr 0
[10] ATM 1: SEQ(3) ex_atm_cell-@11 (A4 GREEN 5) created
[16] ATM 1: SEQ(3) ex_atm_cell-@11 (A4 GREEN 5) sent by drvr 0
[16] ATM 1: SEQ(2) SHORT_LONG ex_atm_sequence-@5 done
Last specman tick - stop_run() was called
Normal stop - stop_run() is completed
Checking the test ...
Checking is complete - 0 DUT errors, 0 DUT warnings.

The format of the output is as follows:

[time] short-name: SEQ(depth)message

Following are the various types of messages:

• Starting the MAIN sequence


• Creation of sequences
• Grabbing or ungrabbing drivers by sequences
• Ending sequences
• Creation of data items
• Sending of data items by driver
• Rerunning a driver
• Quitting a sequence (using the quit() method)
• Stopping a sequence (using the stop() method)
• Releasing a stopped sequence from a grab
You can get the trace list of the driver with the following methods:

• get_trace_list(): Returns a list of all sequences and items handled by the


list of any_sequence_item sequence driver
• get_item_trace_list(): Returns a list of only the items handled (sent) by the
list of any_sequence_item sequence driver
• get_sequence_trace_list(): Returns a list of only the sequences handled by the
list of any_sequence sequence driver

5-68 e Reuse Methodology


Sequences: Constructing Test Scenarios
trace sequence

Also, there is a method, any_sequence.post_trace(), which gets called for every sequence just after a
trace message about it gets printed. This is useful for breakpoints.

5.12.1.1 trace sequence Configuration


trace sequence uses the new message mechanism with the tag TRACE_SEQUENCE. It outputs
messages at the following verbosity levels:

LOW • When starting and ending sequences that were started using start_sequence()
• When rerunning a sequence driver
• When executing the default body of the MAIN sequence
MEDIUM • When do-ing sequences (at the beginning and end)
• When stopping or quitting sequences (using stop() or quit())
HIGH • When do-ing sequence items (at the beginning and end)

By default, trace sequence messages are printed to screen. You can also print the messages to file.

To direct the output of the trace sequence messages to file:

1. Add a dedicated file logger for the trace sequence messages.

2. Configure the new logger to accept messages with the TRACE_SEQUENCE tag and the appropriate
verbosity.

3. (Optional if you do not want trace sequence messages printed to screen also) Remove the
TRACE_SEQUENCE tag from the list of tags accepted by sys.logger.

Note You must do this step in the run phase and not at pre-run.

Example
extend sys {

-- Add a dedicated file logger logger


trace_seq_logger: message_logger is instance;

-- Configure the new logger to accept accept trace sequence messages


keep trace_seq_logger.to_file == "trace_seq_output.txt";
keep trace_seq_logger.to_screen == FALSE;
keep trace_seq_logger.verbosity == FULL;
keep trace_seq_logger.tags == {TRACE_SEQUENCE};

e Reuse Methodology 5-69


Sequences: Constructing Test Scenarios
wave sequence

-- (Optional) Prevent trace sequence messages from printing to screen


run() is also {
specman_command("set message -logger=sys.logger -remove
-tags={TRACE_SEQUENCE}");
};
};

For more information, see Chapter 6 “Messaging”.

5.12.2 wave sequence

Syntax
wave seq[uence] [num]

Description
The wave sequence command adds the specified BFM sequence driver (default: all of them) to the
waveform viewer. The num is according to the numbering of the show sequence command. For each
sequence driver, the following 6 lines are added to the waveform:

struct Shows the e path of the sequence driver (constant).


item Shows the nice_string() of the current item being sent by the sequence
driver. Reverts to “XXX” when no item is being sent.
do_line Actual source line of do that produced this item, with comments.
do_location Location of that do, for example, “at line 44 in @foo”.
sequence The nice_string() of the sequence containing the do.
parent_sequence The nice_string() of its parent sequence.

5.12.3 show sequence

Syntax
show seq[uence] [num]

Description
The show sequence command shows all sequence drivers.

5-70 e Reuse Methodology


Sequences: Constructing Test Scenarios
Customizing Display of Trace and Debug Output

If you specify a num, it shows the trace list of the sequence driver with the index num
(driver.get_index()==num).

The trace list output is shown in a window. The format looks as follows:
Sequences and items in ex_atm_driver-@1 =
0. drvr 0 0: MAIN ex_atm_sequence-@2
1. drvr 0 1: PARALLEL_3 ex_atm_sequence-@3
2. drvr 0 2: SHORT_LONG ex_atm_sequence-@4
3. drvr 0 2: SHORT_LONG ex_atm_sequence-@5
4. drvr 0 2: SHORT_LONG ex_atm_sequence-@6
5. drvr 0 3: ex_atm_cell-@7 (A1 GREEN 2)
6. drvr 0 3: ex_atm_cell-@8 (A1 BLUE 2)
7. drvr 0 3: ex_atm_cell-@9 (A1 GREEN 1)
8. drvr 0 3: ex_atm_cell-@10 (A3 RED 1)
9. drvr 0 3: ex_atm_cell-@11 (A4 GREEN 5)
10. drvr 0 3: ex_atm_cell-@12 (A4 RED 5)
11. drvr 0 3: ex_atm_cell-@13 (A1 GREEN 1)
12. drvr 0 3: ex_atm_cell-@14 (A4 RED 5)

Verisity recommends initially using trace seq to see all output directly on the screen. Then, as output
becomes too much, use trace seq log_only with show seq to see only the desired sequence drivers.

5.12.4 Customizing Display of Trace and Debug Output


For sequences, nice_string() returns the kind followed by the instance name (for example, “RED
atm_sequence-@2”).

For items, nice_string() returns the instance name (for example, “atm_cell-@2”).

You can customize the output of nice_string() by extending or overriding the method.

Example 1 Default Output


[6] ATM 1: SEQ(1) SIMPLE ex_atm_sequence-@20 created
[6] ATM 1: SEQ(2) ex_atm_cell-@23 created

Example 2 Extending nice_string()


// Append the prefix ABCD to the item format.
// For example, "ABCD atm_cell-@23"
extend ex_atm_cell {
nice_string() : string is also {
result = append("ABCD ", result);
};
};

e Reuse Methodology 5-71


Sequences: Constructing Test Scenarios
Sequence-Related Methods

[6] ATM 1: SEQ(1) SIMPLE ex-atm_sequence-@20 created


[6] ATM 1: SEQ(2) ABCD ex_atm_cell-@23 created

Example 3 Overriding nice_string()


// Describe the item in custom format.
// For example, "atm_cell-@2 (A1 GREEN 5)"
extend ex_atm_cell {
nice_string() : string is only {
result = append(me, "(", dest, color, length, ")");
};
};

[6] ATM 1: SEQ(1) SIMPLE ex_atm_sequence-@20 created


[6] ATM 1: SEQ(2) ex_atm_cell-@23 (A1 GREEN 1) created

5.13 Sequence-Related Methods


This section includes:

• start_sequence() on page 5-72


• stop() on page 5-73
• grab() on page 5-74
• ungrab() on page 5-75
• is_blocked() on page 5-76
• is_grabbed() on page 5-77
• current_grabber() on page 5-77
• is_relevant() on page 5-78
• last() on page 5-78

5.13.1 start_sequence()
This method of any_sequence is used to initiate the run of a sequence.

Syntax
[sequence-exp.]start_sequence()

5-72 e Reuse Methodology


Sequences: Constructing Test Scenarios
stop()

Parameters
None

Description
start_sequence() is a non-time-consuming method that starts the body() TCM of the sequence. Use this
method instead of starting the body() TCM directly. When doing so, a new sequence tree is executed.

Notes
• The start_sequence() of the MAIN sequence is called automatically by the driver.
• Before calling the start_sequence() of all sequences other than the MAIN sequence, you must
generate the sequence and connect the driver to the sequence using either a constraint or procedural
code.
• The parent_sequence field of a started sequence is NULL. A started sequence has no parent sequence,
because it serves as the root of a new sequence tree.

See Also
• Figure 5-9 on page 5-92

5.13.2 stop()
This method of any_sequence is used to terminate the run of a sequence.

Syntax
[sequence-exp.]stop()

Parameters
None

Description
stop() is a non-time-consuming method that terminates the execution of body() (if such exists) by
killing its thread. This might become useful if, for example, you want to terminate a sequence in the
middle upon interrupt and execute an alternative sequence instead.

e Reuse Methodology 5-73


Sequences: Constructing Test Scenarios
grab()

Notes
• Stopping a sequence also stops its containing tree. To stop only the sequence’s subsequence tree,
make sure that the sequence is started (not done) by its parent sequence.
• Stopping is done on a cycle boundary, so some non-time-consuming actions in the stopped sequence
might still be executed after the sequence itself was stopped.
• When stopping a sequence, the event stopped is emitted both for the stopped sequence and its root.
• When a sequence is stopped, it and all of its subsequences are released from the grab.
• For correct behavior of stop() for virtual sequences, make sure that the method get_sub_drivers()
of the virtual driver is implemented correctly and returns all BFM drivers to which the sequence and
its subsequences might send items. This is also important when stopping a BFM sequence that was
done by a virtual sequence. For more information about virtual sequences, see “Using Virtual
Sequences” on page 5-25.

5.13.3 grab()
This method of any_sequence lets sequences have an exclusive control over a sequence driver.

Syntax
[sequence-exp.]grab(driver) @sys.any

Parameters

driver A BFM sequence driver expression.

Description
grab() is a blocking TCM that grants its calling sequence an exclusive access to driver. A sequence that
wants exclusivity can call grab(driver). This grants exclusive access to that sequence and its
subsequences from the moment grab() returns (perhaps, after a slight delay) until the sequence calls a
corresponding ungrab(driver). During this grabbing period, the sequence driver belongs to the
sequence. The driver drives only the items that were done by the grabbing sequence or its subsequences.

When a sequence driver belongs to a sequence, only that sequence can send items to the sequence driver.
All other sequences are blocked from sending (that is, their items remain blocked).

5-74 e Reuse Methodology


Sequences: Constructing Test Scenarios
ungrab()

Notes
• Virtual drivers cannot be grabbed, because they do not schedule items.
• Sequence drivers cannot be grabbed while they execute a do action on a sequence item. The grab is
granted immediately after the completion of the do action.
• Exclusive control means that the sequence and all its subsequences can use the sequence driver. All
other calls are blocked until ungrab().
• When grabbing a sequence driver, make sure that the is_relevant() method of the sequence that grabs
the driver returns TRUE. This averts a situation in which the driver cannot send items.
• grab() is hierarchical. If a sequence s1 grabs the sequence driver and then a sequence s2 enclosed
by s1 also grabs the sequence driver, there will be no delay as long as s2 has the sequence driver
within s1. So, for example, s3 (the brother of s2) cannot access the sequence driver. Only when s2
ungrabs does s3 finally get access, but everything outside s1 is still blocked.
• grab() is somewhat similar to lock(), but it is different in the following respects:
• grab() is hierarchical.
• grab() interacts with how items are sent.
• Rerunning a driver cancels the grab. If a sequence grabbed the driver before driver.rerun() was
called, the sequence must regrab the driver. If a sequence was blocked while waiting to get the grab,
then it is released without grabbing the driver. For more information, see “Resetting and Rerunning
Sequences” on page 5-39.

See Also
• grab_test.e in the ex_atm/examples directory (an example of grabbing and ungrabbing)
• ungrab() on page 5-75

5.13.4 ungrab()
This method of any_sequence stops sequences from having an exclusive control over a sequence driver.

Syntax
[sequence-exp.]ungrab(driver)

e Reuse Methodology 5-75


Sequences: Constructing Test Scenarios
is_blocked()

Parameters

driver A BFM sequence driver expression.

Description
ungrab() is a non-time-consuming method that releases the driver from the exclusive control of the
sequence that was previously granted by calling grab().

Notes
• A virtual driver cannot be ungrabbed, because it does not schedule items.
• Calling ungrab() when a sequence did not grab the driver results in error.

See Also
• grab_test.e in the ex_atm/examples directory (an example of grabbing and ungrabbing)
• grab() on page 5-74

5.13.5 is_blocked()
This method is valid for BFM sequences only. It indicates whether a sequence is blocked from sending
items. It happens when another sequence that is not an ancestor has grabbed the sequence driver.

Syntax
[sequence-exp.]is_blocked(): bool

Parameters
None

Description
is_blocked() is a non-time-consuming method that returns TRUE if the sequence is blocked by another
sequence that grabbed the sequence driver.

5-76 e Reuse Methodology


Sequences: Constructing Test Scenarios
is_grabbed()

See Also
• grab() on page 5-74

5.13.6 is_grabbed()
This method is valid for BFM sequence drivers only. It indicates the grab status of the sequence driver.

Syntax
[driver-exp.]is_grabbed(): bool

Parameters
None

Description
is_grabbed() is a non-time-consuming method that returns TRUE if the sequence driver is grabbed by a
sequence.

See Also
• grab() on page 5-74

5.13.7 current_grabber()
This method is valid for BFM sequence drivers only. It indicates which sequence (if any) has exclusive
control over a sequence driver.

Syntax
[driver-exp.]current_grabber(): any_sequence

Parameters
None

e Reuse Methodology 5-77


Sequences: Constructing Test Scenarios
is_relevant()

Description
current_grabber() is a non-time-consuming method that returns the sequence that currently has
exclusive control over the sequence driver. It returns NULL if no sequence currently has exclusive
control over the sequence driver.

See Also
• grab() on page 5-74

5.13.8 is_relevant()
This method is valid for BFM sequences only. It indicates whether the sequence is currently relevant for
do-ing items.

Syntax
[sequence-exp.]is_relevant(): bool

Parameters
None

Description
is_relevant() is a non-time-consuming method that returns TRUE if the sequence is currently allowed to
do items. By default, this method returns TRUE. You can implement it to respond to the changing
conditions of the simulation. It is particularly useful for sequences used by reactive agents.

5.13.9 last()
This method is valid for BFM sequence drivers only. It enables access to previously sent items in the
sequence driver.

Syntax
[driver-exp.]last(index): item

5-78 e Reuse Methodology


Sequences: Constructing Test Scenarios
last()

Parameters

index The index in the sequence history. 0 is the currently sent item, 1 is the
previous item, and so on.

Return Value

item The item that was created index items ago by the sequence. The return value
is NULL if such item does not exist.

Description
last() is a non-time-consuming method that lets you directly access items in the history of the sequence:

• last(0) returns the item currently being driven in (or the last item that was driven in, if there is no
item currently being driven in).
• last(1) returns the item before last(0), and so on.
The length of the history is determined by the field num_of_last_items in the sequence driver, which can
be constrained by the user. The default is 1.

Notes
• last(i) results in an error if i >= num_of_last_items.
• The maximum value for num_of_last_items is 1024.
• num_of_last_items is a static property of the BFM driver. Therefore, it cannot be changed during the
run.

Example 1
You could create a sequence that alternates colors from red to green as follows:
extend packet {
keep color == (driver.last(0) is a GREEN packet ? RED : GREEN);
};

Example 2
You could configure the buffer to store the last 10 items (instead of the default 1 item) as follows:
extend packet_seq_driver {
keep num_of_last_items == 10

e Reuse Methodology 5-79


Sequences: Constructing Test Scenarios
Sequence-Related Pseudo-Routines

};

Notes
• The is a construct is a convenient way to also avoid checking for non-NULL.
• For efficiency, in the sequence driver you might want to set Boolean flags that summarize the last()
information. In that case, the constraint can refer to the Boolean flags rather than last().
• You can also use last()-based constraints in sequences (not just items).
• The last() buffer is cleared upon driver.rerun().

5.14 Sequence-Related Pseudo-Routines


This section includes:

• in_sequence() on page 5-80


• in_unit() on page 5-81

5.14.1 in_sequence()
This pseudo-routine can be used inside sequences and items.

Syntax
[exp.]in_sequence(sequence_type) [(name)]

Parameters

exp An item, sequence, or a BFM sequence driver expression. If exp is missing,


me is used.

sequence_type Any type or subtype of a sequence (that is, it inherits from any_sequence).

name Reference for the found sequence.

Description
The in_sequence() routine returns TRUE if exp is an item or a sequence that was created using do inside
a sequence of type sequence_type (at any depth). If name is specified, it assigns the found sequence to
name.

5-80 e Reuse Methodology


Sequences: Constructing Test Scenarios
in_unit()

If exp is a BFM sequence driver sd, then in_sequence() returns TRUE if sd.last(0) returns TRUE.

in_sequence() can be used in constraints to determine whether an item is inside a specific sequence
type. This allows enforcing constraints on every item in the sequence tree under a specific sequence.
Therefore, this kind of constraint is called a tree constraint. It is useful when you want to say something
like:

“Every ATM cell under the FOO sequence should be green, regardless of how far down it is in the
hierarchy.”

Example
extend ex_atm_cell {
keep in_sequence(FOO ex_atm_sequence) => color == GREEN;
// Implements the condition above

keep in_sequence(BAR ex_atm_sequence) (B) => len == B.len1;


// If this cell is somewhere under a BAR ex_atm_sequence,
// then set len to this sequence's len1 field
};

Of course, the in_sequence() pseudo-routine can also be used in normal procedural code. For example:
if in_sequence(BAR ex_atm_sequence) (B) then {
print B.len1;
};

5.14.2 in_unit()
This pseudo-routine can be used anywhere.

Syntax
[exp.]in_unit(unit_type) [(name)]

Parameters

exp A struct. If exp is missing, me is used.

unit_type Any type or subtype of a unit.

name Reference for the found unit.

e Reuse Methodology 5-81


Sequences: Constructing Test Scenarios
Sequence Interface

Description
in_unit() returns TRUE if you are inside such a unit (at any depth). If name is specified, it assigns the
found unit to name.

Note
• in_unit(foo) is equal to: try_enclosing_unit(foo) != NULL. The motivation behind this routine is
to make it shorter and similar to in_sequence() as well as to enable tree constraints.

See Also
• “Writing Tests Using Sequences” on page 5-20

5.15 Sequence Interface


The sequence model consists of:

item Inherits from any_sequence_item


sequence Inherits from any_sequence so that any sequence struct that you create has both
the any_sequence interface and the any_sequence_item interface
driver Inherits from any_sequence_driver

The following tables contain the full list of methods and fields for “any_sequence_item Interface”,
“any_sequence Interface”, and “any_sequence_driver Interface”.

Table 5-2 any_sequence_item Interface

Struct Member Description


Read Only Member (can only be accessed)

get_depth(): int Depth from the sequence driver, valid from pre-generation.

get_driver(): driver_name Return the driver for an item.

!parent_sequence: any_sequence; Backpointer to the sequence in which an item was created.


Assigned automatically in the pre_generate() of the item.
Read/Write Member (can also be set, constrained, or implemented)

driver: driver_name Driver for the item, soft-constrained to be its parent sequence’s
driver.

5-82 e Reuse Methodology


Sequences: Constructing Test Scenarios
Sequence Interface

Table 5-2 any_sequence_item Interface (continued)

Struct Member Description

nice_string(): string is empty A short string representing the item for tracing. It is used by
trace sequence, wave sequence, and show sequence (see
“Tracing and Debugging Sequences” on page 5-67).

The default implementation returns the value of to_string().

Notes
• The information in this section also applies to sequences.
• The driver field is not defined in any_sequence_item. For this field to be defined, you must use the
item in a sequence statement.
• The get_driver() method is declared as undefined in any_sequence_item. For this method to be
defined, you must use the item in a sequence statement.
• Never use is only on the pre_generate() or post_generate() of items or sequences. The
parent_sequence and driver of fields are assigned in the pre_generate() of any_sequence_item.

Table 5-3 any_sequence Interface

Struct Member Description


Read Only Member (can only be accessed)

get_depth(): int Depth from the sequence driver, valid from pre-generation.

get_driver(): Return the driver for a sequence.


driver_name

!parent_sequence: Backpointer to the sequence in which this sequence was created. Assigned
any_sequence; automatically in pre_generate() of the sequence if such a parent exists.

get_index(): int Starts at 0 and gets incremented after every do.


Provides a declarative style.

grab(driver: Grab the sequence driver for exclusive access and returns when you have
any_sequence_driver) exclusive access.
@sys.any is undefined

is_blocked(): bool Indicate whether the sequence is blocked.

is_relevant(): bool Apply a condition for performing a do item action, so that the do action
will not be scheduled until is_relevant() returns TRUE.

e Reuse Methodology 5-83


Sequences: Constructing Test Scenarios
Sequence Interface

Table 5-3 any_sequence Interface (continued)

Struct Member Description

start_sequence() Starts sequence activity by starting body().

Note Call this method instead of starting body() directly.

See also Figure 5-9 on page 5-92.

stop() Terminates my body(), if it exists.

ungrab(driver: Releases the grab on a sequence driver and returns immediately.


any_sequence_driver)
is undefined
Read/Write Member (can also be set, constrained, or implemented)

driver: driver_name Driver for the sequence, soft-constrained to be its parent sequence’s
driver.

nice_string(): string is A short string representing the sequence for tracing. It is used by trace
empty sequence, wave sequence, and show sequence (see “Tracing and
Debugging Sequences” on page 5-67).

The default implementation returns the kind followed by the instance


name (for example, “RED atm_sequence-@2”).

@ended Emitted immediately after body() is finished.

@started Emitted just before body() is called.

body() @driver.clock is Main method called by do of parent sequence after it generates the current
empty sequence.

kind: kind_name The kind field that determines which sequence it is (within its when
family).

mid_do(s: Hook method called in the middle of do, just after s is generated and
any_sequence_item) before it is executed by calling its body() TCM.
is empty;

post_body() @sys.any Hook method called after body() when sequence is started using the
is empty; start_sequence() method.

post_do(s: Hook method called at end of do, just after the execution of s.body().
any_sequence_item)
is empty;

5-84 e Reuse Methodology


Sequences: Constructing Test Scenarios
Sequence Interface

Table 5-3 any_sequence Interface (continued)

Struct Member Description

post_trace() Gets called for every sequence just after a trace message about it gets
printed. (Useful for breakpoints.)

pre_body() @sys.any Hook method called before body() when sequence is started using the
is empty; start_sequence() method.

pre_do(is_item: bool) Hook TCM called at start of a do performed by the sequence. ‘is_item’
@sys.any is empty; specifies whether you are in a context of do-ing an item or a sequence.

Note Some of the methods in Table 5-3 above are inherited from the any_sequence_item interface
shown in Table 5-2 on page 5-82.

Table 5-4 any_sequence_driver Interface

BFM
Struct Member Description Only
Read Only Member (can only be accessed)

current_grabber(): any_sequence Indicates which sequence (if any) has exclusive Yes
control over a sequence driver.

get_current_item(): Returns the item currently being sent. (NULL if the Yes
any_sequence_item BFM is currently idle.)

get_index(): int Returns index of this sequence driver in the No


all-driver list.

get_item_trace_list(): list of Returns a list of the items handled (sent) by the Yes
any_sequence_item sequence driver (the item sublist of the trace log).

Note The list is populated only if the trace


sequence command was activated in On or Log
Only mode.

get_next_item(): item_name This TCM should be called in PULL_MODE to Yes


@clock receive the next item from the BFM driver. This
TCM is blocked until there is an item to do in the
driver.

See also Figure 5-12 on page 5-95.

e Reuse Methodology 5-85


Sequences: Constructing Test Scenarios
Sequence Interface

Table 5-4 any_sequence_driver Interface (continued)

BFM
Struct Member Description Only

get_num_items_sent(): int Returns count of items sent (excluding Yes


current_item, if any).

get_sequence_trace_list(): list of Returns a list of the sequences handled by the Yes


any_sequence sequence driver (the sequence sublist of the trace
log).

Note The list is populated only if the trace


sequence command was activated in On or Log
Only mode.

get_trace_list(): list of Returns a list of all sequences and items handled by Yes
any_sequence_item the sequence driver (the full trace log).

Note The list is populated only if the trace


sequence command was activated in On or Log
Only mode.

is_grabbed(): bool Indicates the grab status of the sequence driver. Yes

last(index): any_sequence_item Enables access to previously sent items in the Yes


sequence driver.

try_next_item(): item_name This TCM should be called in PULL_MODE when Yes


@clock the BFM has to receive an item or perform some
default behavior. Unlike get_next_item(), in case
there is no available item waiting to be done in the
current cycle, this TCM returns NULL.

Note try_next_item() returns in the same cycle if


there is no pending do action. However, if a do
action started execution, then try_next_item()
might take longer than a cycle, for example, if you
extend the pre_do() TCM to take longer than a
cycle.

See also Figure 5-13 on page 5-96.

5-86 e Reuse Methodology


Sequences: Constructing Test Scenarios
Sequence Interface

Table 5-4 any_sequence_driver Interface (continued)

BFM
Struct Member Description Only
Read/Write Member (can also be set, constrained, or implemented)

bfm_interaction_mode: Specifies the way the driver and the BFM interact Yes
bfm_interaction_mode_t with each other. Possible options are
PULL_MODE (the default) and PUSH_MODE. It
can be constrained.

See also “BFM-Driver Interaction Mode” on page


5-44.

max_random_count: int Used in setting the maximum number of No


subsequences in a RANDOM or MAIN sequence.
keep soft max_random_count ==
MAX_RANDOM_COUNT; // Defined to
// be 10

max_random_depth: int Used for setting the maximum depth inside No


RANDOM sequences. (Beyond that depth,
RANDOM creates only SIMPLE sequences.)
keep soft max_random_depth ==
MAX_RANDOM_DEPTH; // Defined
// to be 4

num_of_last_items: int Used for setting the length of the history of Yes
previously sent items. Default is 1.

gen_and_start_main: bool Enable or disable automatic generation and launch No


of the MAIN sequence upon run. Default is TRUE
(MAIN sequence is generated and started).

check_is_relevant() For forcing a driver to recheck the relevance (value Yes


of is_relevant()) for each sequence that has items
in the driver’s item queue. It can be useful when
something has changed in the BFM that affects the
relevance of some sequences.

e Reuse Methodology 5-87


Sequences: Constructing Test Scenarios
Sequence Interface

Table 5-4 any_sequence_driver Interface (continued)

BFM
Struct Member Description Only

delay_clock() @sys.any This TCM can be used to emit the driver’s clock No
with some intercycle delay to let the BFM export
its state before activation of sequences in a specific
cycle.

Note This TCM should be activated INSTEAD


of connecting the clock to another event.

event clock The main clock. Should be tied to some temporal No


formula by users during the sequence driver
hooking.

event item_done Synchronization event for the do action in Yes


PULL_MODE. When working in PULL_MODE,
you must emit this event to complete the do item
and let the driver get more items using
get_next_item().

See also “Sequence Driver Unit” on page 5-7.

get_sub_drivers(): list of For virtual sequence drivers, this method is to be Virtual


any_sequence_driver is empty filled in by the writer of the specific sequence only
driver. It should return the list of subdrivers of the
sequence driver. For a BFM sequence driver, it
should be left unchanged, that is, return an empty
list.

read(address: list of bit): list of bit For implementing a DUT-independent interface. No


@clock is undefined;
See also: “DUT-Independent Read/Write Interface”
on page 5-41

regenerate_data() is empty Regenerates driver’s data upon rerun(). No

See also “Resetting and Rerunning Sequences” on


page 5-39.

5-88 e Reuse Methodology


Sequences: Constructing Test Scenarios
Predefined Sequence Kinds

Table 5-4 any_sequence_driver Interface (continued)

BFM
Struct Member Description Only

send_to_bfm(seq_item: When working in PUSH_MODE, sends the item to Yes


item_name) @clock is empty the corresponding BFM. To be implemented by
users as part of hooking.

This method is called automatically (when working


in PUSH_MODE).

wait_for_sequences() @sys.any This TCM is called to delay the return of Yes


try_next_item() and let sequences create items. It
can also be called in other locations to help
propagation of activity (for example, among
several layers of sequences). It can also be
overridden to implement a different scheme than
the default one.

write(address: list of bit, data: list For implementing a DUT-independent interface. No


of bit) @clock is undefined;
See also “DUT-Independent Read/Write Interface”
on page 5-41.

Notes
• Some of the driver members are relevant only for BFM drivers. See the last column in the table above.
• Never use is only on the pre_generate() or post_generate() of drivers. The list of previously sent
items of the driver is initialized in the post_generate() of the driver.
• Never use is only on the run() or rerun() of drivers. Some important initializations are performed
in those methods.

5.16 Predefined Sequence Kinds


There are three predefined sequence kinds: MAIN, RANDOM, and SIMPLE. The following sections
describe their implementation.

• “MAIN Sequence” on page 5-90


• “RANDOM Sequence” on page 5-90
• “SIMPLE Sequence” on page 5-90

e Reuse Methodology 5-89


Sequences: Constructing Test Scenarios
MAIN Sequence

5.16.1 MAIN Sequence


This sequence subtype is defined directly under the sequence driver and is started by default. It is used
as the root for the whole sequence tree.
extend MAIN sequence_name {
count: uint;
!sequence: sequence_name;

keep soft count > 0;


keep soft count <= MAX_RANDOM_COUNT;
keep sequence.kind not in [RANDOM, MAIN];

body() @driver.clock is only {


for i from 1 to count do {
do sequence;
};
};
};

5.16.2 RANDOM Sequence


This sequence subtype is used for creating random scenarios based on SIMPLE and user-defined
sequence subtypes.
extend RANDOM sequence_name {
count: uint;
!sequence: sequence_name;

keep soft count > 0;


keep soft count <= MAX_RANDOM_COUNT;
keep sequence.kind not in [RANDOM, MAIN];
keep depth_from_driver >= driver.max_random_depth =>
sequence.kind == SIMPLE;

body() @driver.clock is only {


for i from 1 to count do {
do sequence;
};
};
};

5.16.3 SIMPLE Sequence


This sequence subtype generates and executes a single item.

5-90 e Reuse Methodology


Sequences: Constructing Test Scenarios
BFM-Driver-Sequence Flow Diagrams

extend SIMPLE sequence_name {


!seq_item: item;
body() @driver.clock is only {
do seq_item;
};
};

5.17 BFM-Driver-Sequence Flow Diagrams


This section contains diagrams to show how the BFM, the driver, and the sequences interact with each
other:

• “sequence.start_sequence() Flow” on page 5-92


• “do Subsequence Flow” on page 5-93
• “do Item Flow in Push Mode” on page 5-94
• “do Item Flow in Pull Mode Using get_next_item()” on page 5-95
• “do Item Flow in Pull Mode Using try_next_item()” on page 5-96

e Reuse Methodology 5-91


Sequences: Constructing Test Scenarios
sequence.start_sequence() Flow

5.17.1 sequence.start_sequence() Flow


Figure 5-9 sequence.start_sequence() Flow
Sequence Driver Sequence

start_sequence()
- Parent sequence is NULL.
- Sequence is already generated.
- Driver is not NULL.

trace: “Starting sequence.”


sequence is added to the driver’s trace list”.
The sequence driver emit @started.
does not schedule
sequences but only Start TCM that:
- Calls pre_body() TCM
items. Therefore, when - Calls body() TCM
starting a sequence, no - Calls post_body() TCM
synchronization is done emit @ended.
between the driver and
the started sequence.
Return of start_sequence()

Note: This flow does not depend on the bfm_interaction_mode

Figure 5-9 describes the flow when starting a sequence using the start_sequence() method.

For more information on the start_sequence() method, see “start_sequence()” on page 5-72.

5-92 e Reuse Methodology


Sequences: Constructing Test Scenarios
do Subsequence Flow

5.17.2 do Subsequence Flow


Figure 5-10 do Subsequence Flow
Sequence Driver (driver) Sequence
(1) (n)
do subsequence

Call pre_do() TCM, with is_item = FALSE


The sequence driver Generate subsequence with:
- parent_sequence = sequence
does not schedule
- driver = sequence.driver (by constraint)
sequences but only
subsequence is added to the driver’s trace list.
items. Therefore, when
Trace: “subsequence created”.
do-ing a sequence, no
synchronization is done Call mid_do().
between the driver and Emit @subsequence.started.
the doing sequence or Call subsequence.body().
the done subsequence. Emit @subsequence.ended.
Trace: “subsequence done”.
Call post_do()

End of do subsequence

Note: This flow does not depend on the bfm_interaction_mode.

Figure 5-10 describes the flow when do-ing a subsequence.

For more information on the do action, see “Activating Items and Subsequences” on page 5-13.

e Reuse Methodology 5-93


Sequences: Constructing Test Scenarios
do Item Flow in Push Mode

5.17.3 do Item Flow in Push Mode


Figure 5-11 do Item Flow in Push Mode
BFM Driver Sequence
(1) (1) (n)
Choose a do action to be
executed on a do item
first-come-first-served
The do action is listed in the driver’s queue.
basis, considering
grabbers, and Wait for the driver acknowledgement.
sequence.is_relevant().
Acknowledge the sequence. Call pre_do() TCM, with is_item = TRUE.
Generate item with:
- parent_sequence = sequence
- driver = sequence.driver (by constraint)
item is added to the driver’s trace list”.
Wait until item is generated. Trace: “item created”.
Call mid_do().
Add item to driver’s last() buffer.
Acknowledge the driver that item is
ready to be sent.
Sends item to DUT. Call send_to_bfm (item).
Emit @item_done. Wait for @driver.item_done.
Trace: “item sent by driver”.
Call post_do().
End of do item.

Note: This flow occurs when driver.bfm_interaction_mode == PUSH_MODE.

Figure 5-11 describes the flow when do-ing an item when driver.bfm_interaction_mode is set to
PUSH_MODE.

For more information on the do action, see “Activating Items and Subsequences” on page 5-13.

For more information on driver.bfm_interaction_mode, see “Hooking the Sequence Driver to the
Environment” on page 5-9.

5-94 e Reuse Methodology


Sequences: Constructing Test Scenarios
do Item Flow in Pull Mode Using get_next_item()

5.17.4 do Item Flow in Pull Mode Using get_next_item()


Figure 5-12 do Item Flow in Pull Mode Using get_next_item()
BFM Driver Sequence
Call driver.get_next_item().
Choose a do action to be do item
executed on a The do action is listed in the driver’s queue.
first-come-first-served
basis, considering
grabbers, and Wait for the driver acknowledgement.
sequence.is_relevant().
Acknowledge the sequence. Call pre_do() TCM, with is_item = TRUE.
Generate item with:
- parent_sequence = sequence
- driver = sequence.driver (by constraint)
item is added to the driver’s trace list”.
Wait until item is generated. Trace: “item created”.
Call mid_do().
Add item to driver’s last() buffer.
Acknowledge the driver that item is
Get next_item() returns. ready to be sent.
Sends item to DUT.
Emit @item_done. Wait for @driver.item_done.
Trace: “item sent by driver”.
Call post_do().
End of do item.

Note: This flow occurs when driver.bfm_interaction_mode == PULL_MODE.

Figure 5-12 describes the flow when do-ing an item when driver.bfm_interaction_mode is set to
PULL_MODE and driver.get_next_item() is used to receive items from the driver.

For more information on the do action, see “Activating Items and Subsequences” on page 5-13.

For more information on driver.bfm_interaction_mode, see “Hooking the Sequence Driver to the
Environment” on page 5-9.

For more information on driver.get_next_item(), see Table 5-4 on page 5-85.

e Reuse Methodology 5-95


Sequences: Constructing Test Scenarios
do Item Flow in Pull Mode Using try_next_item()

5.17.5 do Item Flow in Pull Mode Using try_next_item()


Figure 5-13 do Item Flow in Pull Mode Using try_next_item()
BFM Driver
First of:
Call driver.try_next_item() {
choose a do action
}
{
wait_for_sequences()
}
A do action is chosen before
wait_for_sequences returns?

No Yes

try_next_item()
returns with NULL. Continue as in
Create a default item.
get_next_item() flow.
Send item to the DUT. try_next_item()
returns an item.

Notes:
• This flow occurs when driver.bfm_interaction_mode == PULL_MODE.
• try_next_item() might take more than a cycle, in case a do is hosen and pre-do() takes
more than a cycle.

Figure 5-13 describes the flow when do-ing an item when driver.bfm_interaction_mode is set to
PULL_MODE and driver.try_next_item() is used to receive items from the driver.

For more information on the do action, see “Activating Items and Subsequences” on page 5-13.

For more information on driver.bfm_interaction_mode, see “Hooking the Sequence Driver to the
Environment” on page 5-9.

For more information on driver.try_next_item(), see “Applying Default Behavior When No Item Is Done”
on page 5-48 and Table 5-4 on page 5-85.

5.18 Sequence Deprecation


• “Method sequence.start() Deprecation” on page 5-97
• “Field sequence Deprecation” on page 5-97
• “Sequence item Deprecation” on page 5-99

5-96 e Reuse Methodology


Sequences: Constructing Test Scenarios
Method sequence.start() Deprecation

5.18.1 Method sequence.start() Deprecation


All sequences currently have a method named start(). As start is now an e keyword, the name of this
method must be changed to something that does not conflict. Therefore, from Specman 4.3, the start()
method of any_sequence changes to start_sequence().

Note Currently the default severity of this deprecation is IGNORE. You will not get any warning or
error message unless you change the severity level.

Associated Notification IDs


DEPR_SEQUENCE_START_KEYWORD

Sample Notification Message


If any sequence uses the start() method and you have set the severity level to WARNING, you will
receive a message like the following:
*** Warning: DEPR_SEQUENCE_START_KEYWORD: The keyword 'start' is used as
an identifier. Replace the method any_sequence.start() with
any_sequence.start_sequence()
at line 50 in @seq
my_sequence.start();
For more information, search help for 'DEPR_SEQUENCE_START_KEYWORD'.

For more information on the deprecation process, see “The Deprecation Process for Syntactic Changes”
in the e Language Reference.

5.18.2 Field sequence Deprecation


MAIN and RANDOM sequences currently have a field named “sequence”. As sequence is now an e
keyword, the name of this field must be changed to something that does not conflict. From Specman 4.3,
the “sequence” field changes as follows:

• The name of the MAIN sequence field under a sequence driver changes from “sequence” to
“main_sequence”.
• Under the MAIN sequence, the name of the field “sequence” changes to “sub_sequence”.
• Under the RANDOM sequence, the name of the field “sequence” changes to “sub_sequence”.
Note Currently the default severity of this deprecation is IGNORE. You will not get any warning or
error message unless you change the severity level.

e Reuse Methodology 5-97


Sequences: Constructing Test Scenarios
Field sequence Deprecation

To use the new field names:


• Constrain the sequence driver flag using_new_sequence_naming to TRUE.
keep using_new_sequence_naming == TRUE;

This enables the new names for the “sequence” field in the driver and its associated sequences.

Associated Notification IDs


DEPR_SEQUENCE_FIELD_KEYWORD

Sample Notification Message

If your code uses the old name for the MAIN sequence field under a sequence driver and you have set
the severity level to WARNING, you will receive a message like the following:
*** Warning: DEPR_SEQUENCE_FIELD_KEYWORD The keyword 'sequence' is used
as an identifier. Replace 'sequence' of my_sequence_driver with
'main_sequence' after constraining
my_sequence_driver.using_new_sequence_naming to TRUE.
For more information, search help for 'DEPR_SEQUENCE_FIELD_KEYWORD'

If your code uses the old sequence field name under MAIN and you have set the severity level to
WARNING, you will receive a message like the following:
*** Warning: DEPR_SEQUENCE_FIELD_KEYWORD The keyword 'sequence' is used
as an identifier. Replace 'sequence' of MAIN'kind my_sequence with
'sub_sequence' after constraining
my_sequence_driver.using_new_sequence_naming to TRUE.
For more information, search help for 'DEPR_SEQUENCE_FIELD_KEYWORD'

If your code uses the old sequence field name under RANDOM and you have set the severity level to
WARNING, you will receive a message like the following:
*** Warning: DEPR_SEQUENCE_FIELD_KEYWORD The keyword 'sequence' is used
as an identifier. Replace 'sequence' of RANDOM'kind my_sequence with
'sub_sequence' after constraining
my_sequence_driver.using_new_sequence_naming to TRUE
For more information, search help for 'DEPR_SEQUENCE_FIELD_KEYWORD'

For more information on the deprecation process, see “The Deprecation Process for Syntactic Changes”
in the e Language Reference.

5-98 e Reuse Methodology


Sequences: Constructing Test Scenarios
Sequence item Deprecation

5.18.3 Sequence item Deprecation


The SIMPLE sequence currently has a field named “item”. As item is now an e keyword, the name of
this field must be changed to something that does not conflict. Therefore, from Specman 4.3, the “item”
field of the SIMPLE sequence changes to “seq_item”.

Note Currently the default severity of this deprecation is IGNORE. You will not get any warning or
error message unless you change the severity level.

Associated Notification IDs


DEPR_SEQUENCE_ITEM_KEYWORD

Sample Notification Message


If the SIMPLE sequence uses the “item” field and you have set the severity level to WARNING, you will
receive a message like the following:
*** Warning: DEPR_SEQUENCE_ITEM_KEYWORD: The keyword 'item' is used as
an identifier. Replace 'item' of SIMPLE'kind my_sequence with 'seq_item'
after constraining my_sequence_driver.using_new_sequence_naming to
TRUE.
For more information, search help for 'DEPR_SEQUENCE_ITEM_KEYWORD'.

For more information on the deprecation process, see “The Deprecation Process for Syntactic Changes”
in the e Language Reference.

5.19 Known Limitations


Following are the known limitations of the sequence model:

• “Same Item Cannot Be Used in Two Different Sequences” on page 5-99


• “Item Children Cannot Be Created with Like Inheritance before Sequence Statement” on page 5-100
• “Sequences Are Supported Only from Version 4.1” on page 5-100

5.19.1 Same Item Cannot Be Used in Two Different


Sequences

Description
You cannot use the same item type in two different sequence statements in the same environment.

e Reuse Methodology 5-99


Sequences: Constructing Test Scenarios
Item Children Cannot Be Created with Like Inheritance before Sequence Statement

Workaround
Create two (or more) subtypes and use the subtypes in the sequences (a different subtype for each
sequence type).

Example
You could create two different sequences for ATM cells as follows:

1. Define the type to create the subtypes.

For example:
type cell_seq_kind: [A, B];

2. Add the type to the item for which you want to create sequences.

For example:
extend ex_atm_cell {
seq_kind: cell_seq_kind;
};

3. Use the sequence statement to create two different sequences for the two different subtypes.

For example:
sequence atm_A using item=A ex_atm_cell;
sequence atm_B using item=B ex_atm_cell;

5.19.2 Item Children Cannot Be Created with Like Inheritance


before Sequence Statement
Specman does not allow the addition of fields to a struct that already has like children. The sequence
statement adds fields and methods to the item struct. Therefore, if you have created like item children
before the sequence statement, Specman reports an error when the sequence statement occurs.

Example
sequence my_seq using item=my_item;
// Create children of my_item only after the sequence statement
struct my_new_item like my_item {...}

5.19.3 Sequences Are Supported Only from Version 4.1


The sequences package can be run only on top of Specman version 4.1 or higher.

5-100 e Reuse Methodology


6 Messaging
The messaging feature gives a unified and standardized mechanism for writing and controlling debug
printout messages to the screen and to files.

This chapter includes:

• “Introduction” on page 6-1


• “Basic Messaging” on page 6-6
• “The Message Action” on page 6-16
• “Message Loggers” on page 6-20
• “Messaging Command Interface” on page 6-23
• “Messaging Procedural Interface” on page 6-32
• “Configuring Loggers via Constraints” on page 6-37
• “The short_name_path() of a Unit” on page 6-40
• “Colors for Message Actions” on page 6-42
• “Recommended Methodology for the Message Action in eRM eVCs” on page 6-43

6.1 Introduction
The messaging feature is a centralized and flexible mechanism to print out useful text messages to the
screen or to log files. It lets the code developer easily insert formatted and colored messages into the
code. It provides the end user with powerful and flexible controls to selectively enable or disable groups
of messages.

e Reuse Methodology 6-1


Messaging
Messaging Requirements

The three most typical uses for messages are:

Summaries Printing summary information at the beginning or end of significant chunks of


activity
Tracing Printing detailed trace messages during the simulation, upon interesting events
Debugging Printing detailed debug messages during the run, to help the user or developer
debug unexplained behaviors

One of the most important aspects of messages is that they give end users a standard and unified
interface. For ease of use, those who receive ready-to-use eVCs must be able to debug or trace activity
inside the code. This is even more important when the user has multiple eVCs and will need all printouts
from all eVCs to have similar formatting and a standard centralized mechanism to control and filter the
messages. The messaging feature provides all of these capabilities.

Messages are different from plain out() and outf() printouts. They have a standard-format prefix that can
be turned on or off by the user.

Messages are also different from dut_error() printouts. They do not signify failure, and they do not
increment error or warning counters.

This section includes:

• “Messaging Requirements” on page 6-2


• “Messaging Solution” on page 6-3
• “Message Logger Struct Deprecation” on page 6-4
• “About This Chapter” on page 6-5

6.1.1 Messaging Requirements

Uniformity
Many Specman users have invented their own company-wide or project-wide feature for writing
message output. This is often a macro on top of the out() action.

However, a uniform way to write message output is needed so that output appears in a standard format
(for example, starting with the current time). There must also be a standard way to configure message
output at various verbosity levels.

The need for uniformity is especially great in the context of eVCs, because an integrator using several
eVCs might want to make changes to all of the output (for example, disable all messages or enable all
messages).

6-2 e Reuse Methodology


Messaging
Messaging Solution

Simplicity and Flexibility of Writing Message Actions


Writing message actions should be fairly easy. Moreover, if some output must be created by a printing
method, users should be able to call it (that is, it should not be just a glorified out() action).

Simplicity and Flexibility of Enabling and Disabling Message Actions


It should be easy to enable and disable specific message actions.

In addition to writing to the screen, users should also be able to divert the output of specific message
actions to one or more files. This avoids the need to write a separate file logging facility.

User Control of Output Format


Users should be able to control at least the prefix of the output.

Minimal Performance Overhead When Off


The overhead of message actions should be very low when turned off.

Furthermore, there should be a way to compile a specified subset of the message actions so that they
incur no overhead at all.

6.1.2 Messaging Solution


When executed, the message action creates a message and sends it to a message logger. Each message
logger can be configured to filter messages in various ways, to format the enabled messages in various
ways (adding the time, name of the unit, and so on), and to send them to various destinations
(files/screen).

The message loggers are instantiated by the programmer in the unit hierarchy, and then configured by
the end user via constraints (though they can also be configured via commands or procedurally).

Note There is a predefined message logger, sys.logger. Therefore, defining new loggers is not strictly
necessary. We recommend doing so for finer control.

Users can use the interactive show message commands to see all loggers and message actions.

Users can use the interactive set message commands to change the configuration of loggers (for
example, to request more or less output).

Examples
• Add some message actions, and put a logger in the unit:

e Reuse Methodology 6-3


Messaging
Message Logger Struct Deprecation

unit my_dsp {

foo() is {
...
message(LOW, "Starting transmission");
-- LOW verbosity means this is an important message that will
-- be shown even when verbosity is set to 'LOW'
...
message(MEDIUM, "Sending packet ", pkt);
-- MEDIUM verbosity means this is a less important message
...
};

logger: message_logger is instance;


-- Instantiate a message logger for this unit. When activated,
-- it will handle all message actions executing in this unit
-- or in any unit or struct under it.
};

• Configure the logger via constraints:


extend sys {
dsp: my_dsp is instance;
keep dsp.logger.tags == {NORMAL}
keep dsp.logger.verbosity == LOW;
-- This logger will only look at important messages
keep dsp.logger.to_file == "dsp_results.elog";
-- Send it also to a file (it goes to the screen by default)
};

• Optionally use commands:


As configured above, sys.dsp.logger will send only important (LOW verbosity) messages to file and
screen. If, while debugging, you find that you also want less important messages, you can issue the
following command from the Specman prompt:
set message -logger=sys.dsp.logger -verbosity=HIGH

6.1.3 Message Logger Struct Deprecation


Beginning in Specman 4.1.1, message loggers are units, rather than structs.

Note We recommend not referencing or accessing HDL signals and external ports from message
loggers.

Associated Notification IDs


DEPR_MESSAGE_LOGGER

6-4 e Reuse Methodology


Messaging
About This Chapter

Sample Notification Message


If your code declares message loggers as structs, you will see a message like the following (or a full
error message if Specman cannot apply the new semantics automatically):
*** Warning: DEPR_MESSAGE_LOGGER: The message logger <message_logger>
is a unit, and therefore must be declared with an "is instance" clause".
Suggestion: Please add an "is instance" clause.
at line 97 in logging_info.e
logger: message_logger; -- struct declaration, not unit declaration

For more information, search help for 'DEPR_MESSAGE_LOGGER'

Example
Prior to Specman 4.1.1, message loggers were structs and not units. Therefore, the following code ran
without error in earlier releases:
unit A {
logger: message_logger; // Incorrect
};

Beginning in Specman 4.1.1, message loggers are units and not structs. Therefore, you must declare
message loggers with the “is instance” clause required by units:
unit A {
logger: message_logger is instance; // Correct
};

For more information on the deprecation process, see “The Deprecation Process for Syntactic Changes”
in the e Language Reference.

6.1.4 About This Chapter


The remainder of this chapter consists of two main parts:

• “Basic Messaging” on page 6-6: This is a QuickStart that might satisfy all of your needs. Even if you
plan to use some of the more advanced aspects of the messaging feature, we still recommend reading
this section before going on to the rest of the chapter.
• Everything after “Basic Messaging”: The rest of the chapter provides detailed explanation of the
various aspects of the messaging feature. Even if the “Basic Messaging” section seems to satisfy all
of your needs, you might want to glance at “Summary of Messaging Commands” on page 6-23 to see
all available commands (everything you can do to message loggers). We also encourage everyone to
read “Recommended Methodology for the Message Action in eRM eVCs” on page 6-43.

e Reuse Methodology 6-5


Messaging
Basic Messaging

6.2 Basic Messaging


This section is intended as a QuickStart of the message feature. Some readers might find that this section
answers all of their questions. Other readers might require additional information. Either way, we
recommend reading this section before reading the rest of this chapter.

This section includes:

• “Basic Message Action” on page 6-6


• “Basic Message Loggers” on page 6-8
• “Basic Messaging Configuration” on page 6-13

6.2.1 Basic Message Action


This section provides basic information on the message action. After reading this section, see “The
Message Action” on page 6-16 if you need more details.

This section includes:

• “Example Message Action” on page 6-6


• “Format of Message Output” on page 6-6
• “Message Syntax” on page 6-7

6.2.1.1 Example Message Action


Following is an example of a message action:
monitor_bus() @clock is {
wait @reset_ended;
message(LOW, "Bus ", bus_num, " is done with reset");
-- This message will be shown even when the verbosity is set to LOW
while TRUE {
wait @grant;
extract_next_burst();
message(MEDIUM, "Bus ", bus_num, " granted");
-- Verbosity level is MEDIUM
-- String to print is "Bus ", bus_num, " granted"
};
};

6.2.1.2 Format of Message Output


The message output can be in three formats: short, long, or none. The default format is short.

6-6 e Reuse Methodology


Messaging
Basic Message Action

You can change the format via constraints or commands.

Examples
• short
[12030] AHB_0 M1: Bus 3 is done with reset

Notes
• The color of the short name (“AHB_0” in the example above) can be customized per eVC.
• The color of the time (“[12030]” in the example above) alternates between BLACK and GRAY
as the time changes.
• long
[12030] AHB_0 M3 (HIGH) at line 32 in @ex_bus_watch in ex_bus_unit-@4:
Bus 3 is done with reset
• none
Bus 3 is done with reset

6.2.1.3 Message Syntax

Syntax
message([tag], verbosity, exp, …) [action-block]

messagef([tag], verbosity, format, exp, …) [action-block]

Parameters

tag Used to direct the output (for example, to a file). Default is NORMAL

verbosity Suggested use:


NONE: Messages that cannot be disabled
LOW: Once per run (reset messages, and so on)
MEDIUM: Once per transaction
HIGH: More detailed
FULL: Even more detailed

e Reuse Methodology 6-7


Messaging
Basic Message Loggers

action-block Can include output-producing actions or method calls:


message(HIGH, "Master ", me, " received packet:"){
print the_packet;
};

6.2.2 Basic Message Loggers


This section provides basic information on message loggers. After reading this section, see “Message
Loggers” on page 6-20 for more information.

This section includes:

• “message_logger” on page 6-8


• “sys.logger” on page 6-8
• “Message Tags and Message Destinations” on page 6-9
• “How Loggers Relate to Message Actions” on page 6-10
• “Multiple eVCs with Loggers” on page 6-11
• “Configuring Loggers” on page 6-12

6.2.2.1 message_logger
message_logger is a unit whose job is to manage the output from message actions by:

• Filtering it (for example, ignoring actions above verbosity LOW)


• Formatting it
• Sending the result to one or more destinations (screen, files)
By default, sys contains one instance of a logger, namely sys.logger. eVC developers can add logger
instances to other units within their eVC. Some examples from our golden eVCs are:

• vr_xbus_env.logger, which goes to the screen


• vr_xbus_env.file_logger, which sends to a file the output from very specific message actions (marked
with a special tag)

6.2.2.2 sys.logger
sys.logger is predefined. It starts with LOW verbosity, NORMAL tag, and sending messages to the
screen. You can change these settings using constraints or commands.

6-8 e Reuse Methodology


Messaging
Basic Message Loggers

For example, in Figure 6-1, the second message action has a verbosity of FULL, but the logger is set to
verbosity LOW. As a result, only the first message action is printed to screen.

Figure 6-1 sys.logger

sys.logger is predefined:
• Looks at messages with NORMAL tag
• Starts with LOW verbosity
• Sends messages to the screen
sys
logger (NORMAL (LOW) => screen) This message action will show on the
screen.
foo()@clock is {
message (LOW, "Reset is done");
message (FULL, "Packet", packet_num, "completed:" …);
};
This message action will not (because sys.logger only
accepts LOW verbosity messages)

To change the verbosity, use constraints or commands.


Command example: "set message FULL"

To enable that second message as well, you must set the verbosity of the logger to FULL via the
following command:
set message FULL

6.2.2.3 Message Tags and Message Destinations


The eVC developer must decide what tags to use in the eVC and how to use them (that is, which tags to
send to screen, which tags to send to file(s), and so on).

The default tag for a message action (if none was specified) is NORMAL.

By default, sys.logger recognizes messages with NORMAL tag. The default for all other loggers is to
ignore all tags. They have an empty tag list “{}”. Therefore, to activate a logger other than sys.logger,
you must set its tag list using commands or constraints.

The default destination for all loggers is to send messages to the screen only.

e Reuse Methodology 6-9


Messaging
Basic Message Loggers

6.2.2.4 How Loggers Relate to Message Actions


Figure 6-2 eVC with Screen and File Loggers

vr_xbus.elog

sys
logger (NORMAL (LOW) => screen)

vr_xbus_env_u
logger (NORMAL (FULL) => screen) This message:
• Goes to file_logger (accepts
file_logger (VR_XBUS_FILE (HIGH) => vr_xbus.elog) the tag)
foo()@clock is { • Does not go to sys.logger
message (LOW, "Reset…"); (accepts only NORMAL tag)
message (FULL, "Packet…");
message (VR_XBUS_FILE, MEDIUM, "RESET: …");
};

The logger-message logic is as follows:

1. Each logger has a list of destinations, a list of tags it recognizes, and a list of enabled messages.

2. Messages are handled by each logger on the way to sys that recognizes the message tag and has a
destination that closer loggers did not have.

3. Messages can be sent to multiple destinations but they only have one chance to go to any particular
destination.

• If a message is enabled in a handling logger, it is formatted and sent to all destinations of the
logger (except any destinations of a closer handling logger).
• If a message is not enabled in a handling logger, it is not sent to any of the logger’s destinations
(and it will never be sent to any of the logger’s destinations). (See Figure 6-3.)

6-10 e Reuse Methodology


Messaging
Basic Message Loggers

Figure 6-3 Subunit Logger Blocking a Message

• Each message action goes to


the closest logger that
vr_xbus.elog recognizes its tag (scanning
from origin unit up to sys)
• Other loggers will not see it
sys (unless they send to a unique
destination)
logger (NORMAL (FULL) => screen)

vr_xbus_env
logger (NORMAL (LOW) => screen) This message will not be
shown. It is disabled for
file_logger (VR_XBUS_FILE (HIGH) => vr_xbus.elog) vr_xbus_env.logger and will
not continue to sys.logger
foo()@clock is { because of the above rules
message (LOW, "Reset…");
message (FULL, "Packet…");
message (VR_XBUS_FILE, MEDIUM, "RESET: …");
};

6.2.2.5 Multiple eVCs with Loggers


You can have multiple eVCs with loggers. Each eVC should have a screen logger and zero or more file
loggers.

Figure 6-4 below shows an example of multiple eVCs with loggers. In the figure, the verbosity level of
each logger is shown in parentheses. The vr_xbus instance on the left is set to FULL verbosity. The
vr_xbus instance on the right is set to MEDIUM verbosity. (The logger for that instance is set to disabled
(transparent); but because sys.logger is set to MEDIUM verbosity, you still get messages from that
instance up to MEDIUM verbosity.) In the example, the file loggers of the two vr_xbus instances are
directed to two different files (left_xbus.elog and right_xbus.elog).

e Reuse Methodology 6-11


Messaging
Basic Message Loggers

Figure 6-4 Multiple eVCs with Loggers

Because this
logger ignores all
left_xbus.elog tags, screen right_xbus.elog
messages from
this unit continue
to sys.logger
sys
logger (NORMAL (MEDIUM) => screen)
This message
soc_env_u logger (no tags=> screen) action is being
filtered
vr_xbus_env_u vr_xbus_env_u
logger (NORMAL (FULL) => screen) logger (no tags=> screen)

file_logger (VR_XBUS_FILE (HIGH) => left_xbus.elog) file_logger (VR_XBUS_FILE (HIGH) => right_xbus.elog)

foo()@clock is { foo()@clock is {
message (LOW, "Reset…"); message (LOW, "Reset…");
message (FULL, "Packet…"); message (FULL, "Packet…");
message (VR_XBUS_FILE, MEDIUM, message (VR_XBUS_FILE, MEDIUM,
"RESET: …"); "RESET: …");
}; };

6.2.2.6 Configuring Loggers


The default configuration for a message logger is:

• Verbosity NONE (that is, ignoring all input). The one exception is sys.logger, which defaults to
verbosity LOW.
• Writing to the screen
• Not writing to any file
• Empty tag list {}
These parameters (and many others) can be changed using:

• Constraints (most commonly)


• Commands (at any time during the run)
• An API (which parallels the commands)
• The eRM Utility (see “Controlling Messaging” on page 8-16)

6-12 e Reuse Methodology


Messaging
Basic Messaging Configuration

6.2.3 Basic Messaging Configuration


This section provides basic information on controlling messaging. However, the messaging feature
offers much more power and complexity than what is presented here. After reading this section, if you
require more details, see:

• “Messaging Command Interface” on page 6-23


• “Messaging Procedural Interface” on page 6-32
• “Configuring Loggers via Constraints” on page 6-37
• “The short_name_path() of a Unit” on page 6-40
• “Colors for Message Actions” on page 6-42
• “Recommended Methodology for the Message Action in eRM eVCs” on page 6-43
Note Even if this basic section seems to satisfy all of your needs, you might want to glance at
“Summary of Messaging Commands” on page 6-23 to see all available commands (everything you can
do with message loggers). We also encourage everyone to read “Recommended Methodology for the
Message Action in eRM eVCs” on page 6-43.

This section includes:

• “How eVC Writers Configure Messaging” on page 6-13


• “How Integrators Configure Messaging” on page 6-15
• “How Users Configure Messaging” on page 6-15

6.2.3.1 How eVC Writers Configure Messaging


eVC writers can configure messaging by adding screen and file loggers per eVC and possibly per agent.

Examples
• Add a screen logger.
extend vr_xbus_env {
// Use message_logger defaults: verbosity NONE, to_screen,
// Empty tag list {}
logger: message_logger is instance;
};
Note By default, each logger uses verbosity NONE, and its tag list is empty. This passes the
control to sys.logger until the logger is explicitly enabled.

• Add a file logger:

e Reuse Methodology 6-13


Messaging
Basic Messaging Configuration

extend vr_xbus_env {
file_logger: message_logger is instance;
keep soft file_logger.verbosity == LOW;
// Have all actions from all instances of eVC go to vr_xbus.elog
keep soft file_logger.to_file == "vr_xbus.elog";
keep soft file_logger.to_screen == FALSE;
keep soft file_logger.tags == {VR_XBUS_FILE};
-- Some writers might want to use NORMAL tag (same as screen)
};

Specifying the Short Name and Short Name Color in Message Output
eVC writers can specify the short name and short name color in message output per eVC. For example,
they might want the short name output to appear as follows:

[12030] AHB_0 M1: Bus 3 is done with reset

Note The “AHB_0” in the above example is printed to screen as green.

The following code might be used to make this happen:


extend vr_xbus_env {
short_name(): string is {
return append(name);
-- This assumes there is an instance-id field called "name",
-- containing, for example, XBUS_0, etc.
-- The same must also be done for agents (if you want them to
-- have a short name).
};
short_name_style(): vt_style is {
return GREEN;
-- This will paint XBUS_0 in GREEN. (It will also be shown with
-- the eVC's banner).
-- We recommend leaving agent names BLACK.
};
};
Note Color is removed from text before sending it to files.

Tips
• eVC writers might want more than one file logger. For example, they might want a data_file_logger
and a packet_file_logger, each showing information at different abstraction levels. To do this, use
separate tags for each file logger.
• eVC writers might want to have some hidden message actions that are enabled only to debug some
algorithm within the eVC. To do this, use special tags (for example, VR_XBUS_CRC).

6-14 e Reuse Methodology


Messaging
Basic Messaging Configuration

• The eVC documentation should contain the following tables:


• Loggers (with associated tags)
• Message action categories (what is shown in verbosities LOW, MEDIUM, HIGH, and FULL)
along with a list of special tags, if any

6.2.3.2 How Integrators Configure Messaging


Integrators are those who build a VE (verification environment) for test writers out of multiple eVCs and
other components.

Integrators might configure messaging as follows:

• Split file output per eVC instance (if wanted). For example:
extend vr_xbus_env {
keep soft file_logger.to_file == append(name,".elog");
};

• Change the color of an eVC if not unique in the env.


• Change the verbosity of eVC instances as needed.

6.2.3.3 How Users Configure Messaging


Users can configure messaging for many purposes. Some typical configurations are as follows:

• To get more information on a specific instance. For example:


extend XBUS_1 vr_xbus_env {
keep soft logger.verbosity == FULL;
keep soft logger.tags == {NORMAL};
};

• To get more information during the run. This is done via commands. For example:
// Get more messages from all units
set message HIGH

// Get more messages from only one logger


set message -logger=sys.left_xbus.logger -verbosity=FULL

// Get all HIGH messages from a particular module


set message -add –verbosity=HIGH @foo

// Add all messages with specific text


set message -add "...Arbitration ..."

e Reuse Methodology 6-15


Messaging
The Message Action

// Disable all messages to sys.logger


set message NONE

// Make a logger ignore the NORMAL tag


set message -logger=sys.left_xbus.logger -ignore_tags
Note You can only issue the above commands after initial generation, because the only logger that
exists prior to generation is sys.logger. For more information, see “When to Issue Message
Commands” on page 6-49.

• To make some messages stand out. For example, you could color all reset messages purple as follows:
set message –style=PURPLE "...Reset..."

• To change output format. For example, you can set the output format to long as follows:
set message –format=long

• To show the current configuration.


show message // Shows summary of all loggers
show message –l=all -full // Shows full details per logger
show message –actions // Shows all message actions in files

6.3 The Message Action


This section provides a detailed explanation of the message action.

This section includes:

• “message Syntax” on page 6-16


• “message Semantics” on page 6-17
• “Examples of the Message Action” on page 6-17
• “Output Appearance” on page 6-18
• “Recommended Verbosity Usage” on page 6-19
• “message_tag” on page 6-20

6.3.1 message Syntax


message([tag], verbosity, exp, …) [action-block]

messagef([tag], verbosity, format_exp, exp, …) [action-block]

6-16 e Reuse Methodology


Messaging
message Semantics

6.3.2 message Semantics


When a message() or messagef() action is executed, the following happens:

• If there are no handling loggers for the action, then the action is skipped. (For details on how Specman
computes the list of handling loggers for a message action, see “How Loggers Handle Messages” on
page 6-21.)

• If there are handling loggers for the action, the action creates a message (consisting of a list of string
plus related information) and sends it to all of the handling loggers. Those loggers then format the
message and send it to the screen or to files.
• For message(), the first string in the message is created by appending all of the expressions like out()
does. For messagef(), the first string is created using the format-exp, as in outf().
messagef(), like outf(), does not automatically add a \n (carriage return) after the message. Hence,
the users should normally end the format-exp with a \n. For example:
messagef(HIGH, "Packet number %d seen\n", i);
messagef() also allows things like:
messagef(HIGH, "And the winner is: ") {
if winner != NULL then {
out(winner.name);
} else {
out("Nobody");
};
};
However, if the whole messagef() output (including the optional action block) does not end with a
\n, then an extra \n is added.
• Finally, if an action block exists, it gets executed. It will probably contain further output-producing
actions, calls to reporting methods, and so on. The output of all of those is added, as a list of string,
to the message. As the message action can be enabled or disabled, code in an action block should not
modify the flow of the simulation in any way. Time-consuming operations in an action block are
strictly disallowed.

6.3.3 Examples of the Message Action


message(LOW, "Bus ", bus_num, " is done with reset");
-- Output this message at verbosity LOW.

messagef(MEDIUM, "Packet number %d has arrived\n", packet_num);


-- Output this message using a format string, at verbosity MEDIUM.

message(HIGH, "Master ", me, " has received ", the_packet) {

e Reuse Methodology 6-17


Messaging
Output Appearance

print the_packet;
};
-- Output this message and print the packet, at verbosity HIGH.

message(VR_XBUS_FILE, MEDIUM, "Packet ", num, " sent: ", data);


-- Output this message at verbosity MEDIUM.
-- Use VR_XBUS_FILE as the message-tag.

6.3.4 Output Appearance


There are three predefined formats for writing messages. These formats are controlled via the set
message -format command.

Note Users who are not satisfied with the way the three predefined formats look have full
programmatic control over formatting (by extending the format_message() method of the message
logger).

6.3.4.1 Short Format


The short format is the default. It looks as follows:

[time] short-name-path: message

Example
[12030] AHB_0 M1: Bus 3 is done with reset

Typically, short-name-path is predefined. For information on setting short-name-path, see “The


short_name_path() of a Unit” on page 6-40.

Note If short-name-path has not been set, then the default output appears as path-@instance_number.

6.3.4.2 Long Format


The long format looks as follows:

[time] short-name-path (verbosity) source in struct-instance:


message

Note The source and the struct-instance will both be blue hyperlinks in Specview.

Example
[12300] AHB_0 M1 (HIGH) at line 12 in @vr_ahb_send in vr_ahb_bfm-@77:
Bus 3 is done with reset

6-18 e Reuse Methodology


Messaging
Recommended Verbosity Usage

6.3.4.3 No Format (none)


The none format does not add anything to the message specified in the message action.

Example
Bus 3 is done with reset

6.3.5 Recommended Verbosity Usage


The verbosity parameter can be set to NONE, LOW, MEDIUM, HIGH, or FULL.

Lower verbosity implies a more important message.

The set message action refers to verbosity. For example, “set message -verbosity=MEDIUM” enables
all message actions whose verbosity is MEDIUM or lower.

Table 6-1 below shows the recommended usage of verbosity. Keep in mind that each level can assume
that all lower levels are also printing (and hence there is no need to repeat them).

Table 6-1 Verbosity Levels

Level Recommended Use Examples

NONE Critical messages that users will “WARNING: Running in reduced mode”
always want to see. (This level
cannot be disabled.)

LOW Messages that happen once per run or “Master M3 was instantiated”
once per reset.
“Device D6 got out of reset”

MEDIUM Short messages that happen once per “Packet-@36 was sent to port 7”
data item or sequence.
“A write request to pci bus 2 with
address=0xf2223, data=0x48883”

HIGH More detailed per-data-item “Full details for packet-@36:


information, including: len=5
kind=small
• Printing the actual value of the ...”
packet
• Printing subtransaction details
FULL Anything else, including message
prints in specific methods (just to
follow the algorithm of that method).

e Reuse Methodology 6-19


Messaging
message_tag

6.3.6 message_tag
Both message() and messagef() have an optional first parameter of type message_tag.

The type message_tag is initially defined as follows:


type message_tag: [NORMAL];

It can be extended by the user. For example:


extend message_tag: [VR_XBUS_PACKET];

If you do not specify a tag, (that is, if the first parameter of message() is a legal value for verbosity), then
the value NORMAL is prepended. Hence:
message(MEDIUM, "Packet done: ", packet);

is the same as:


message(NORMAL, MEDIUM, "Packet done: ", packet);

Example
Following is an example of specifying a message tag in the message action:
message(VR_XBUS_PACKET, MEDIUM, "Packet ", num, " sent: ", data);
-- This message action only goes to loggers that look for this
-- particular tag "VR_XBUS_PACKET".

Message tags are used for associating specific message actions with a message logger (see “Message
Loggers” on page 6-20).

We expect that most message actions will not specify a tag at all. (In other words, they will use the
default NORMAL tag.) Other tags will be used only in special cases such as:

• Message actions that are specifically targeted for going to a file


• Temporary message actions to be enabled only in a very specific debugging mode (for example, to
see how some algorithm is working)

6.4 Message Loggers


A message logger is a predefined unit, whose job is to manage the output from message actions (filtering
it, formatting it, and sending it to one or more destinations).

Message loggers are defined programmatically and are attached as fields to various units in the unit
hierarchy. For example:

6-20 e Reuse Methodology


Messaging
How Loggers Handle Messages

extend vr_xbus_env {
logger: message_logger is instance;
};

For each message logger you can specify the following things (via methods, commands, or constraints):

• Which subset of the message actions the logger will look at.
By default, each logger uses verbosity NONE, and its tag list is empty. This passes the control to
sys.logger until the logger is explicitly enabled.
• Which subset of the unit instances the logger will look at.
By default, this is the tree starting at the unit the logger is attached to. For example, each
vr_xbus_env.logger looks at the unit subtree under the corresponding vr_xbus_env.
• Which destinations (files or screen) to send output to.
• What format to use.
Typically, loggers are generated at elaboration time before the simulation run begins. You can create a
logger instance at run time, but it must be created as a field and not as a variable.

By default (before any file is loaded) there is just one message logger, called sys.logger. However, we
recommend that each eVC (and, optionally, each agent within the eVC) define one message logger for
writing information to the screen and zero or more message loggers for writing information to files.

Note We recommend not referencing or accessing HDL signals and external ports from message
loggers.

This section includes:

• “How Loggers Handle Messages” on page 6-21


• “Configuring Message Loggers” on page 6-23

6.4.1 How Loggers Handle Messages


Once configured, loggers process message actions in the following manner.

1. Whenever a message action is executed, Specman gathers the list of handling loggers. To compute
that list, Specman:

a. Determines the origin unit where the message action is executed, via get_unit().

Note get_unit() is a method of any_struct. message() and messagef() can be used anywhere
in your code.

b. Gathers all loggers that are looking at that unit.

e Reuse Methodology 6-21


Messaging
How Loggers Handle Messages

These are normally all loggers instantiated in units between the origin unit and sys that recognize
the tag of the message except those loggers explicitly programmed to ignore the origin unit (for
example, by using the set message -units command).
c. Sorts the list of handling loggers on the basis of closest to the message action first and selects
the closest one for each destination.

For example, if get_unit() returned:


sys.soc.xbus_1.agents[3].BFM
then the list might be:
sys.soc.xbus_1.agents[3].logger
sys.soc.xbus_1.logger
sys.soc.xbus_1.file_logger
sys.logger
d. Removes from the list of handling loggers all loggers that ignore the message tag.

2. For each handling logger, Specman:

a. Calls logger.accept_message().

If that method (which is extensible by the user) returns FALSE, then the message is ignored and
will not be processed by this logger any more.
b. Calls logger.format_message() to take the raw message and create a final list of string from it.

c. Sends the created list of string to each of the destinations (file or screen) associated with the
logger.

Example
Suppose only the NORMAL tag exists, and we have:

• A file logger and a screen logger in the XBus env


• A screen logger in the XBus agent
We can set verbosity and destination as follows:
set message -logger=sys.xbus_1.logger HIGH
set message -logger=sys.xbus_1.file_logger HIGH
set message -logger=sys.xbus_1.file_logger -file=xbus_1.elog

And then:
set message -logger=sys.xbus_1.agent_5.logger LOW
-- Assume this logger is configured to send to screen (the default)

6-22 e Reuse Methodology


Messaging
Configuring Message Loggers

If you have a HIGH verbosity message coming from agent_5, then:

• sys.xbus_1.agent_5.logger handles this message for the screen. However, as that logger has only
LOW verbosity messages enabled, the message is not sent to screen.
• sys.xbus_1.file_logger handles this message for the xbus_1.elog file. As that logger has HIGH
messages enabled, this message is sent to the file.

6.4.2 Configuring Message Loggers


There are three ways (covered in detail in the next three sections) to configure loggers. You can use:

• Commands
• Methods of the logger
• Constraints
Commands and methods have almost equivalent power. (In fact, the commands are directly
implemented via the methods.) Configuring via constraints is less flexible, but it should be flexible
enough for most users. If more flexibility is required, you can use the procedural interface to fine-tune
the configuration after generation.

Constraints are used during pre-run generation to set the fields of the logger. Then, during
post_generate(), the logger fields are used to configure the logger.

6.5 Messaging Command Interface


In this section, the command interface receives the most extensive description. The procedural and
constraint interfaces (see the following two sections) are explained by analogy to the commands.

This section first gives a brief look at all of the messaging commands and then goes into detail on each
of them. This section includes:

• “Summary of Messaging Commands” on page 6-23


• “Detailed Explanation of Commands” on page 6-25

6.5.1 Summary of Messaging Commands


This section contains a summary of all messaging commands. It includes:

• “set message Summary” on page 6-24


• “show message Summary” on page 6-25

e Reuse Methodology 6-23


Messaging
Summary of Messaging Commands

6.5.1.1 set message Summary


All of the following commands refer to sys.logger unless you specify the -logger=exp option. You can
replace -logger with -l. Also, you can use -logger=all to do something for all loggers.

Notes
• The filter parameter in some of the commands in Table 6-2 and Table 6-3 specifies a subset of the
message actions to operate on. For example, a common filter is -verbosity as in
set message -verbosity=HIGH, which enables all message actions with a verbosity level of NONE
to HIGH.
• For -add and -replace, the meaning of -verbosity is from NONE to the verbosity specified. For
-remove, the meaning of -verbosity is from the verbosity specified to FULL.
• If no -verbosity is specified, the verbosity of -add and -replace is FULL. If no -verbosity is specified,
the verbosity of -remove is NONE.

Table 6-2 set message Commands

Command Effect

set message [-logger=exp|all] Specify which message actions are watched by


the logger.
[-replace|-add|-remove] [filter]
For details on filter, see “Syntax for filter” on
page 6-27.

set message [-logger=exp|all] -units=exp [on|off] Specify which unit instances are watched by
the logger.

set message [-logger=exp|all] -format=name Specify the format for the logger.

set message [-logger=exp|all] Specify the file flush_frequency for the logger.
-flush_frequency=num

set message [-logger=exp|all] -file=file [on|off] Add or remove files to be written to by the
logger.

set message [-logger=exp|all] -screen [on|off] Turn on and off writing to screen by the logger.

set message -style=style-name [filter] Change all the actions matching the filter to
show the message in specified style. (By
default, all messages are printed as BLACK.)

For details on filter, see “Syntax for filter” on


page 6-27.

6-24 e Reuse Methodology


Messaging
Detailed Explanation of Commands

Table 6-2 set message Commands (continued)

Command Effect

set message [-logger=exp|all] -ignore[_tags] Force the logger to ignore the specified tags.
[=tags|=all]

6.5.1.2 show message Summary


Table 6-3 show message Commands

Command Effect

show message Show a short summary of all loggers, including


each logger’s list of tags, highest verbosity, and
number of message actions.

show message -logger=exp|all [-full] Show medium information for the specified
logger or all loggers (if -logger=all is specified).

Show complete details if -full is specified.

show message -actions [filter] Show all message actions, each with its
associated loggers.

show message -units [=exp] Show all units, each with its associated loggers.

show message -actions -ignore [filter] Show the list of actions (matching filter) whose
tag is ignored by all loggers.

6.5.2 Detailed Explanation of Commands


This section contains a detailed explanation of all messaging commands. It includes:

• “set message Commands” on page 6-25


• “show message Commands” on page 6-31

6.5.2.1 set message Commands


This section includes details on the following commands:

• “set message [-logger=exp|all] [-replace|-add|-remove] [filter]” on page 6-26


• “set message [-logger=l_exp] -units=u_exp [on|off]” on page 6-28
• “set message [-logger=exp|all] -file=file [on|off]” on page 6-29

e Reuse Methodology 6-25


Messaging
Detailed Explanation of Commands

• “set message [-logger=exp|all] -screen [on|off]” on page 6-30


• “set message [-logger=exp|all] -format=format-name” on page 6-30
• “set message [-logger=exp|all] -flush[_frequency]=num” on page 6-30
• “set message -style=style-name [filter]” on page 6-30

set message [-logger=exp|all] [-replace|-add|-remove] [filter]


This command selects a set of message actions specified by the filter, and adds/removes/replaces
(default: -replace) the list of message actions watched by the specified logger (default: sys.logger).

All options add the tag specified in the filter to the list of tags recognized by the specified logger. To
ignore a tag, use set message -ignore_tags (see below).

Following is an explanation of the three options:

-replace Enables the actions specified in filter, and disables all others.

In most cases you want to specify directly (and not incrementally) what each
logger will do. Therefore, -replace is the default. For example:
set message LOW

is the same as:


set message -remove // Remove all
set message -add LOW // Add just what the user specified
-add Enables the actions specified in filter for this logger (in addition to the actions
already enabled). The default for filter is FULL (that is, enable all actions).
-remove Disables the actions specified in filter from this logger. The default for filter is
NONE (that is, disable all actions).

For example, you can say:


set message -replace @vr_xbus*
-- Look at only the 20 message actions in the vr_xbus* modules
set message -add -verbosity=MEDIUM @vr_xsoc*
-- Add on the 10 message actions in the vr_xsoc* modules that have
-- MEDIUM verbosity
set message -remove "...arbitration..."
-- But remove all message actions mentioning "arbitration"

6-26 e Reuse Methodology


Messaging
Detailed Explanation of Commands

Syntax for filter

The set message command has an optional filter parameter, specifying which of the currently loaded or
compiled message actions will be affected.

The syntax for filter is:

[[-verbosity=]verbosity] [-tags=tags-list] [@module-wildcard] ["string"]

Note The order should be exactly as specified above.

[-verbosity=]verbosity Matches the message actions whose verbosity is between LOW and
verbosity (when using set message -add or set message -replace) or
between verbosity and FULL (when using set message -remove).

Note Instead of -verbosity you can omit the switch name and just specify
the value. For example, “set message FULL” is the same as “set message
-verbosity=FULL”.

-tags=tags-list Matches the message actions whose tags are those specified by the list.

Note If the -tags option is not used, then only the message actions whose
tag is NORMAL are affected.

@module-wildcard Matches the message actions residing in the specified module(s).

"string" Matches the message actions whose concatenated string is string. This is
the same string that would be shown using show message.

Consider the following example of a message action:


message(LOW, "Bus ", bus_num, " is done with reset");

The string shown would be: “Bus … is done with reset”. And, for example,
you could match it with:
show message "... reset"
Note In the following example, the string would also be “Bus … is done
with reset”:
messagef(LOW, "Bus %d is done with reset\n", bus_num);

Note The "string" and @module parameters are the same as in the set check command. For more
information, see “set checks” on page 12-1 of the Specman Command Reference.

e Reuse Methodology 6-27


Messaging
Detailed Explanation of Commands

Example
set message -add @vr_ahb*
-- Add all actions in modules matching vr_ahb* to system.logger
set message -remove -verbosity=HIGH @vr_ahb*
-- Remove all message actions with HIGH verbosity in specified modules
set message -add -logger=sys.dsp.logger @vr_dsp*
-- Add to the specified logger all message actions in specified modules
set message -add -logger=sys.packet_logger -tags={VR_XBUS_PACKET}
-- Add to the specified logger all message actions whose message tag is
-- VR_XBUS_PACKET

set message [-logger=l_exp] -units=u_exp [on|off]


This command adds or removes the unit subtree under u_exp to the set of units watched by the specified
logger (default: sys.logger).

For example, the following command removes all units under (and including) the audio_subsystem from
the set of units watched by sys.logger.
set message -units=sys.audio_subsystem off

As detailed in the description of loggers, a message action gets processed by a logger only if that logger
looks at both the executing message action and the unit in which the message action executed (as
determined by get_unit()).

Initially, each logger looks at its native unit tree, that is, the unit tree under the unit to which the logger
is attached. It is an error to specify -unit=some_unit if some_unit is not included in the native unit tree
for the logger.

Note u_exp can be either a unit or a list of units (in which case, the subtrees under each of the units are
turned on or off).

The set message -units command is useful if you want to see less output from one of the many instances
of, say, an eVC. For example, suppose you have:
uarts[10]: list of uart

You can then issue:


set message -units=sys.uarts[3] off
Note Usually you want to have lower verbosity for almost everything, and higher verbosity for just one
or more units. This is best achieved by using lower verbosity in sys.logger and turning the logger(s) of
the desired unit(s) to higher verbosity (without using the -units option at all).

6-28 e Reuse Methodology


Messaging
Detailed Explanation of Commands

set message [-logger=exp|all] -file=file [on|off]


This command adds file to the specified logger, or (if off is specified) removes the file from the specified
logger.

The default extension for file is “.elog”. Thus the following command will write to foo.elog:
set message -logger=sys.main_file_logger -file=foo

Each logger can write to any number of files, in addition to optionally writing to the screen (see “set
message [-logger=exp|all] -screen [on|off]” on page 6-30).

Users often want to log information into separate files (for example, one file per eVC type or one file per
eVC instance, one file altogether, and so on). We recommend using the message action for that purpose
as well. Some points to keep in mind are:

• Several loggers can write to the same file.


We recommend setting the writing to files via constraints (see “Configuring Loggers via Constraints”
on page 6-37).

• We recommend using a message_tag to mark message actions meant for going to loggers that will
write to files. For example, if you would normally want to write to two files (one for packet
information and one for byte information), we suggest defining two tags as in the following example:
extend message_tag: [VR_XBUS_PACKET, VR_XBUS_BYTE];
Then (using a command, a constraint, or a method) you can have only message actions using
VR_XBUS_PACKET go to the packet logger, and so on. With commands, this will look as follows:
set message -logger=sys.packet_logger -tags={VR_XBUS_PACKET}
set message -logger=sys.packet_logger -file=packet_log.elog

• When you use the set message -file=file command, Specman first checks if that file is already open
(via some other set message -file command). If the file is not open, Specman opens it (and writes a
message to the screen indicating that). If the file is already open, Specman simply marks that logger
as also going to that file.
• When you use set message -file=file off, Specman will stop writing to that file. When there are no
more loggers writing to a file, then Specman closes the file (and writes a message to the screen
indicating that).
• Specman flushes the buffer of each file after every n writes to that file, where n starts out as 10 but
can be modified using the set message -flush_frequency command (see “set message
[-logger=exp|all] -flush[_frequency]=num” on page 6-30).

• Every file gets flushed whenever you get to the Specman prompt.
• All files are flushed and closed just before Specman exits. There is no auto-closing at end of test.

e Reuse Methodology 6-29


Messaging
Detailed Explanation of Commands

set message [-logger=exp|all] -screen [on|off]


This command makes a logger write to the screen or stop writing to the screen (if off is specified).

set message [-logger=exp|all] -format=format-name


This command specifies the format of the logger. The format must be a legal value of the type
message_format.

Initially, message_format is defined as:


type message_format: [short, long, none];

Loggers start out with the short format. For details on how these formats influence the output, see
“Output Appearance” on page 6-18.

Note Users can extend message_format and can also format the output programmatically by extending
the method logger.format_message(). For more information, see “Messaging Procedural Interface” on
page 6-32.

set message [-logger=exp|all] -flush[_frequency]=num


This command causes flushing to the disk of each message output file associated with the specified
logger every num writes. The default is every 10 writes.

The message output files are flushed out in any case when quitting Specman and any time you reach the
Specman prompt. However, if you are looking at the output files using, for example, the “tail -f” UNIX
command, you might want to flush out files frequently.

Using set message -flush=1 will cause flushing after each write (but will, of course, have some
performance implications).

Note Using the set message -flush_frequency command also flushes the files immediately (that is,
when the command is issued).

set message -style=style-name [filter]


This command changes the style associated with all specified actions to the requested style. For
example, to color all reset messages purple so that they will stand out, you can use:
set message -style=PURPLE "...Reset..."

Notes
• Initially all messages are printed as BLACK.
• This command is global (to all loggers).

6-30 e Reuse Methodology


Messaging
Detailed Explanation of Commands

• This command only influences the actual message (that is, the information after the colon). You must
use unit.short_name_style() to influence the style of the short_name.

set message [-logger=exp|all] -ignore[_tags] [=tags|=all]


This command forces the logger to ignore the specified tags.

Notes
• If no tags are specified, then NORMAL tag is assumed.
• If “=all” is specified, all tags are ignored, which effectively disables the logger.
• The difference between -ignore_tags and -remove is that -remove eliminates the unique destinations
of a logger for messages with the specified tags, whereas -ignore_tags eliminates the impact of the
logger’s destinations on messages with the specified tags. When -ignore_tags is used, the end result
depends on the remaining loggers on the way to sys. Verbosity might be increased or decreased.

6.5.2.2 show message Commands


This section includes details on the following commands:

• “show message” on page 6-31


• “show message -logger=exp|all [-full]” on page 6-32
• “show message -actions [filter]” on page 6-32
• “show message -units [=exp]” on page 6-32
• “show message -win[dow]” on page 6-32

show message
This command shows a short summary of all loggers. The output looks like the following:
0. sys.logger - NORMAL (HIGH) ,TRACE_SEQUENCE (HIGH) ,TRACE_OBJECTION
(MEDIUM) - 35 actions
1. sys.ex_soc_env.atms[0].logger - 0 actions
2. sys.ex_soc_env.atms[0].file_logger - NORMAL (HIGH) - 24 actions
3. sys.ex_soc_env.atms[1].logger - 0 actions
4. sys.ex_soc_env.atms[1].file_logger - NORMAL (HIGH) - 24 actions
5. sys.ex_soc_env.atms[2].logger - 0 actions
6. sys.ex_soc_env.atms[2].file_logger - NORMAL (HIGH) - 24 actions
7. sys.ex_soc_env.c_bus_env.logger - 0 actions
8. sys.ex_soc_env.c_bus_env.file_logger - 0 actions
9. sys.ex_soc_env.logger - 0 actions

e Reuse Methodology 6-31


Messaging
Messaging Procedural Interface

10. sys.ex_soc_env.file_logger - 0 actions

show message -logger=exp|all [-full]


This command shows information for the specified logger(s).

To see information for all loggers, use:


show message -logger=all

If -full is specified, then all information for the specified loggers is displayed. Otherwise, MEDIUM
information is displayed.

The output of this command looks like the following:


0. sys.logger - NORMAL (HIGH) ,TRACE_SEQUENCE (HIGH) ,TRACE_OBJECTION
(MEDIUM) - 35 actions:
Units: 14 Format: short
Destinations: screen
Note The actual verbosity (HIGH in the above example) represents the current maximum verbosity (as
changed, for example, via a set message command). This can be different from the initial verbosity as
set by constraints (LOW in the above example).

show message -actions [filter]


This command shows all message actions matching filter (default: all message actions).

For each action, it shows the list of loggers looking at it.

show message -units [=exp]


This command shows as a tree all unit instances under exp (default: all unit instances).

For each unit, it shows which loggers are looking at it (closest to the unit first).

show message -win[dow]


This command opens the eRM Utility with various options for loggers, messages, and destinations. (See
“Controlling Messaging” on page 8-16.)

6.6 Messaging Procedural Interface


A message logger has an API, corresponding (more or less) to the commands explained in “Messaging
Command Interface” on page 6-23. This section explains the messaging procedural interface.

6-32 e Reuse Methodology


Messaging
Methods for Setting Configuration

This section includes:

• “Methods for Setting Configuration” on page 6-33


• “Methods for Showing Configuration” on page 6-34
• “Methods Called While Handling Messages” on page 6-34
• “Query Methods for Getting Message Information” on page 6-35

6.6.1 Methods for Setting Configuration


The following methods of message_logger set the configuration. For details on the command
parameters, see “set message Commands” on page 6-25.

set_actions(verbosity: int, tags: list of message_tag, modules: string, text: string,


op: message_operation)

• Adds, removes, or replaces the specified actions for the logger.


• Corresponding command: “set message [-logger=exp|all] [-replace|-add|-remove] [filter]”
set_units(root: any_unit, to: message_on_off)

• Sets the unit tree under root to be either on or off for the message logger.
• Corresponding command: “set message [-logger=l_exp] -units=u_exp [on|off]”
set_format(format: message_format)

• Corresponding command: “set message [-logger=exp|all] -format=format-name”


set_flush_frequency(flush_frequency: int)

• Corresponding command: “set message [-logger=exp|all] -flush[_frequency]=num”


set_file(fname: string, to: message_on_off)

• Corresponding command: “set message [-logger=exp|all] -file=file [on|off]”


set_screen(to: message_on_off)

• Corresponding command: “set message [-logger=exp|all] -screen [on|off]”

e Reuse Methodology 6-33


Messaging
Methods for Showing Configuration

set_style(verbosity: int, tags: list of message_tag, modules: string, text: string, style: vt_style)

• Sets the specified actions to the requested style (for example, GREEN)
• Corresponding command: “set message -style=style-name [filter]”
ignore_tags(tags:list of message_tag)

• Forces the logger to ignore the specified tags

6.6.2 Methods for Showing Configuration


The following methods of message_logger show configuration. For details on the command parameters,
see “show message Commands” on page 6-31.

show_message(all: bool, full: bool)

• Corresponding command: “show message -logger=exp|all [-full]”


show_actions(verbosity: int, tags: list of message_tag, modules: string, text: string)

• Corresponding command: “show message -actions [filter]”


Note This command shows information for all loggers.

show_units(root: any_unit)

• Corresponding command: “show message -units [=exp]”


Note This command shows information for all loggers.

get_tags(): list of message_tag

• Returns the tags currently recognized by the logger

6.6.3 Methods Called While Handling Messages


The following methods are predefined, but they can also be modified by the user.

Note These methods can use the various query methods (see “Query Methods for Getting Message
Information” on page 6-35) to get information about the current message.

extend message_logger {

// Return TRUE if the current message should be enabled.


// By default returns TRUE, but you can set it conditionally

6-34 e Reuse Methodology


Messaging
Query Methods for Getting Message Information

// to FALSE, e.g. if you want to ignore this message after it


// has appeared enough times, etc.
accept_message(): bool is {
return TRUE;
};

// Returns the list of string, which will be sent as-is to the


// file or screen (Specman will add a "\n" at the end of
// each string when printing them to the file/sceen). If you want an
// extra empty line at the end, add a "\n" to the last string.
// By default, this method obeys the current format as described
// in the manual, but you can add more formats or change the meaning
// of the existing formats.
format_message(): list of string is {
... // Compute result according to current format
};
};

For example, if you want the short format to be:

>>> 100: message-text

then you could write:


extend message_logger {
format_message(): list of string is first {
if get_format() == short then {
result = get_message();
result[0] = dec(">> ", sys.time, " ", result[0]);
return result;
};
};
};

6.6.4 Query Methods for Getting Message Information


The following methods are available for use within accept_message() and format_message(). They
return information about the message action that was just executed.

get_action_style(): vt_style

Return the vt_style for the current message action (for example, GREEN)

get_format(): message_format

Return the message format of the current logger

e Reuse Methodology 6-35


Messaging
Query Methods for Getting Message Information

get_message(): list of string

Return the current raw message as produced by the message action

get_message_action_id(): int

Return a unique number identifying the message action

get_verbosity(): message_verbosity

Return the verbosity of the message action

source_location(): string

Return the source location where the message occurred, for example, “At line 12 in @foo”

source_method_name(): string

Return the name of the method where the message occurred, for example, “foo()”

source_struct(): any_struct

Return the actual source struct where the message occurred

source_struct_name(): string

Return the name of the struct type where the message occurred, for example, “packet”

The following example shows the use of query methods for formatting messages:
<'

extend message_logger {

format_message(): list of string is only{


var msg_list := get_message();
var msg := msg_list[0];
var s: string;

-- This code colorizes the msg (-style= <color>)


var style := get_action_style();
if (style != BLACK) {
msg = vt.text_style(style,msg);
};

var current_struct := source_struct();


var short_name_path :=
current_struct.get_unit().short_name_path();

6-36 e Reuse Methodology


Messaging
Configuring Loggers via Constraints

var time := get_time();


var verbosity_str := get_verbosity();

case format {
long: {
s = append(time, short_name_path," (",verbosity_str,") " ,
source_location(), " in ",current_struct,
":\n",msg);
};
short: {
s = append(time, short_name_path,
(short_name_path == NULL ? " " : ": "), msg);
};
none: {
s = append(msg);
};
};

if (msg_list.size() > 1) {
result = {s;msg_list[1..]};
} else {
result = {s};
};
};

};

'>

6.7 Configuring Loggers via Constraints


Loggers should always be generated, usually directly under units.

At post-generation, the logger becomes attached to the unit (specifically, the unit computed by
logger.get_unit()).

In addition, each logger has several constrainable fields (see “Constrainable Fields and Their Default
Values” on page 6-38).

The post_generate() method of a logger uses the generated values of the fields to configure the logger
via the procedural interface described in “Messaging Procedural Interface” on page 6-32.

This section includes:

• “Constrainable Fields and Their Default Values” on page 6-38


• “Using the Constrainable Fields to Configure Loggers” on page 6-38

e Reuse Methodology 6-37


Messaging
Constrainable Fields and Their Default Values

• “Constraining Verbosity” on page 6-39

6.7.1 Constrainable Fields and Their Default Values


The various constrainable fields are used in configuring the message logger during post_generate() of
the logger. The following code shows the constrainable fields and their default values.
extend message_logger {

// The message tags for selecting the actions for this logger
tags: list of message_tag;
keep soft tags == {};

// The verbosity for selecting the actions for the logger


verbosity: message_verbosity;
keep soft verbosity == NONE;

// The modules wildcard for selecting the actions for the logger
modules: string;
keep soft modules == "*";

// The pattern to match against the string in the message action


string_pattern: string;
keep soft string_pattern == "...";

// File name the logger should write to (or none if "")


// Default extension for the file name is ".elog".
to_file: string;
keep soft to_file == "";

// True if we want the message_logger to write to screen


to_screen: bool;
keep soft to_screen == TRUE;
};
Note You can associate only one file with a logger via constraints. Using the procedural/command
interface, you can specify as many files as you like.

6.7.2 Using the Constrainable Fields to Configure Loggers


The various constrainable fields are used in configuring the message logger during post_generate() of
the logger. The following code shows how message loggers are configured.
extend message_logger {

// On post_generate(), configure the message logger according to fields

6-38 e Reuse Methodology


Messaging
Constraining Verbosity

post_generate() is also {
configure_according_to_fields();
};

-- Configure this message logger according to the generatable fields


configure_according_to_fields() is {

set_base_unit(get_unit());

-- Set filtering
set_actions(verbosity,tags,modules,string_pattern,replace);

-- Set destinations
if to_file != "" then {
set_file(to_file, on);
};

if to_screen {
set_screen(on);
};

-- Set misc options


set_format(format);
set_flush_frequency(flush_frequency);
};
};

6.7.3 Constraining Verbosity


You can use constraints in a way similar to commands with an interpretation of -replace.

By default, all loggers have all tags ignored and a verbosity of NONE:
extend message_logger {
keep soft tags == {};
keep soft verbosity == NONE;
};

The one exception is sys.logger, which is defined as:


extend sys {
keep soft logger.verbosity == LOW;
keep soft logger.tags == {NORMAL};
};

Tags are empty by default, because by default we want all messages to be controlled by sys.logger.

This scheme is the same as issuing at the start of the test:

e Reuse Methodology 6-39


Messaging
The short_name_path() of a Unit

set message LOW

If you want one specific logger to be HIGH (and not ignored), use:
extend sys {
keep soft xbus_1.logger.verbosity == HIGH;
keep soft xbus_1.logger.tags == {MY_TAG};
};

If you constrain verbosity to any value above NONE and yet leave the tag list empty, Specman
automatically constrains the tag list to {NORMAL}.

6.8 The short_name_path() of a Unit


short_name_path() is a method of any_unit that returns a shorthand notation for a unit. You must
never modify the short_name_path() directly. Instead, you should extend the short_name() method,
which short_name_path() calls.

This section includes:

• “Motivation” on page 6-40


• “How short_name_path() Works” on page 6-41
• “How short_name_path() Is Computed” on page 6-41

6.8.1 Motivation
The short_name_path() feature provides units with a short name-path, to be used, for example, in the
short format of messages.

For example, the short format for message output is:

[time] short-name-path: message

Example:
[123000] AHB_0 MASTER_1: Received first part of transaction-@33

6.8.2 Syntax
short_name_path(): string

In the example below, “AHB_0 Master_1” is the result of the message action calling
short_name_path().
[123000] AHB_0 MASTER_1: Received first part of transaction-@33

6-40 e Reuse Methodology


Messaging
How short_name_path() Works

6.8.3 How short_name_path() Works


short_name() is defined in any_unit as:
short_name(): string is empty;

In other words, by default short_name() returns an empty string.

You can change this method to return the desired short-name for the unit. For example:
extend vr_ahb_env {
evc_name: vr_ahb_name; // e.g. AHB_0 etc.

short_name(): string is only {


return append(evc_name);
};
};

extend vr_usb_agent {
index: int; // The index in some big list

short_name(): string is only {


return dec("USB agent[", index, "]");
};
};

6.8.4 How short_name_path() Is Computed


The method short_name_path():

1. Collects all of the non-empty short_name() strings along the path from sys to the unit.

2. Appends all the strings with a blank separator.

3. If the result is not empty, returns it. Otherwise, returns something like “vr_xbus_env-@55”.

Notes
• If the eVC and the agent have short_name() defined as non-empty, but the BFM unit within the
agent does not define short_name(), then the short_name_path() for the agent and the BFM will
be the same.
This is acceptable. You do not have to invent short names for all of the leaves of the unit tree. It is
okay for messages coming from the agent and the BFM to all start with something like
“(20000) AHB_0 M1:”. In that case, presumably it either does not matter where exactly the
message is coming from, or it will become clear by the text of the message anyway.

e Reuse Methodology 6-41


Messaging
Colors for Message Actions

• Suppose you have an SoC that contains AHB_0, AHB_1, and AHB_2. If you then construct a new
DUT that contains two instances of that SoC, then it is advisable to define a non-empty short_name()
for the whole SoC to maintain uniqueness of short-name paths.
In this case, the message will start with something like
“[123000] NORTH_RTR AHB_0 MASTER_1: …”.
• Beyond pre-generation, short_name_path() caches the result for performance.

6.9 Colors for Message Actions


This section includes:

• “Basic Color Handling in Specman” on page 6-42


• “any_unit.short_name_style()” on page 6-43
• “Coloring Time” on page 6-43

6.9.1 Basic Color Handling in Specman


In Specman, we now have the official method for coloring Specview text:

vt.text_style(color: vt_style, text: string): string

For example, if you have Specman, you could get some red text by writing:
out("I see red: ", vt.text_style(RED, "Some red text"));

You can use vt.text_style() to colorize any part of your message. For example:
message(LOW, vt.text_style(ORANGE, "Reset"), " is done");

Colors are all uppercase (for example, BLACK).

To see the existing styles (colors), type:


vt.show_styles()

You can use any style you want from the list. We recommend avoiding BLUE (used for hyperlinks) and
both RED and DARK_ORANGE (used for errors).

Note These colors apply only to text going to screen. Text going to file is scrubbed of color
information.

6-42 e Reuse Methodology


Messaging
any_unit.short_name_style()

6.9.2 any_unit.short_name_style()
In addition to short_name(), each unit has a method called short_name_style().

short_name_style() is defined as follows:

short_name_style(): vt_style

The default is BLACK. If you change vt_style to another color, then the message will contain the short
name in that color.

For example, if you write:


extend MASTER vr_ahb_agent {
short_name_style(): vt_style is only {return GREEN};
};

then the word “MASTER_1” in the message output below will also appear green (along with the
short-name path):
[123000] AHB_0 MASTER_1: Received first part of transaction-@33
Note The same style will also appear in the eVC banner that gets written after initial generation.

6.9.3 Coloring Time


The color of the time portion of the message alternates between GRAY and BLACK as the time
changes.

This is done automatically by the logger.

6.10 Recommended Methodology for the Message


Action in eRM eVCs
This section includes:

• “Screen Logger” on page 6-44


• “File Logger(s)” on page 6-44
• “Handling Short Names and Styles” on page 6-46
• “Coloring of Whole Message Actions” on page 6-47
• “Special Tags” on page 6-48
• “Tracing Sequences” on page 6-48

e Reuse Methodology 6-43


Messaging
Screen Logger

• “at_message_verbosity()” on page 6-48


• “Verb Tenses” on page 6-49
• “Soft Constraints” on page 6-49
• “sys.logger” on page 6-49
• “When to Issue Message Commands” on page 6-49
• “Extending message_logger” on page 6-51
• “show message -actions” on page 6-51
• “Scaling the Time Portion of Message Output” on page 6-51

6.10.1 Screen Logger


Each eVC and agent should have a screen logger. For example:
extend vr_xbus_env {
logger: message_logger is instance;
};

We recommend that developers not constrain the tags (accepting all defaults) so that sys.logger can
provide centralized control. To get more information about a particular instance, users can write
something like:
extend XBUS_1 vr_xbus_env {
keep soft logger.verbosity == HIGH;
};
Note Always use soft constraints to allow additional changes later.

6.10.2 File Logger(s)


File loggers are not required, but you should probably have a file logger at the eVC env level. If desired,
you can also have a file logger (and even, in special cases, multiple file loggers) for each agent.

As configured by the eVC developer, we recommend that all of these loggers go to the file
evc_name.elog and start out with LOW verbosity.

Following are two typical cases.

6-44 e Reuse Methodology


Messaging
File Logger(s)

One File Logger Using NORMAL Tag


In this case, the eVC developer decides not to create special message actions for writing to files. Hence,
the normal message actions (NORMAL tag) are also used for sending to a file (depending on verbosity).

The developer defines something like the following:


extend vr_xbus_env {
file_logger: message_logger is instance;
keep soft file_logger.verbosity == LOW;
keep soft file_logger.tags == {NORMAL};
keep soft file_logger.to_file == "vr_xbus.elog";
keep soft file_logger.to_screen == FALSE;
};

End users might choose to have HIGH verbosity for the file logger and LOW verbosity for the screen, or
vice versa. In that case, they could write:
extend vr_xbus_env {
keep soft file_logger.verbosity == HIGH;
keep soft logger.verbosity == LOW;
};

Several Per-Topic File Loggers


In this case, the eVC developer chooses to provide several per-topic file loggers. For example, one
logger might show the raw data (in some special tabular format) while another would show packet-level
traffic (in another special format). In the corresponding message actions, we suggest using tags like the
following:
messagef(VR_XBUS_DATA, MEDIUM, "%5d. %2x %8x\n", index, control, data);

The developer would then define something like the following:


extend vr_xbus_env {
data_file_logger: message_logger is instance;
keep soft data_file_logger.verbosity == LOW;
keep soft data_file_logger.to_file == "vr_xbus.elog";
keep soft data_file_logger.tags == {VR_XBUS_DATA};
keep soft data_file_logger.format == none;
packet_file_logger: message_logger is instance;
keep soft packet_file_logger.verbosity == LOW;
keep soft packet_file_logger.to_file == "vr_xbus.elog";
keep soft packet_file_logger.tags == {VR_XBUS_PACKET};
keep soft packet_file_logger.format == none;
};

e Reuse Methodology 6-45


Messaging
Handling Short Names and Styles

As defined above, the two streams go into the same file. However, end users (or integrators) can decide
to split them any way they like. For example, if there are three instances of the vr_xbus_env,
distinguished by their name (instance_id) field (which would be XBUS_1, XBUS_2, and XBUS_3),
then the end user might want six files, one for each (name, stream) combination. This can be done as
follows:
extend vr_xbus_env {
keep soft data_file_logger.to_file == append(name, "_data.elog");
keep soft packet_file_logger.to_file == append(name, "_packet.elog");
};

Other combinations are easily achieved as well. For example:

• No file logging needed.


• Log everything to one file.
• Log to n separate files, one for each log type.
• Log to m separate files, one for each instance.
• Log to n * m files.
• Anything in between.
Note Each specified file gets created even if it is empty.

6.10.3 Handling Short Names and Styles

Short Names
We recommend that each eVC and each agent have a non-empty short_name(). Typically, this would be
the name (instance_id) field of the eVC or agent. For example:
extend vr_xbus_env {
short_name(): string is {
return append(name);
};
};

This ensures that the full short-name path printed with each message will look something like:
[10340] AHB_1 M2: Reset is done

Notes
• Going lower than the agent level (for example, defining a non-empty short name for the BFM) is
generally not needed. The context is usually clear from the message.

6-46 e Reuse Methodology


Messaging
Coloring of Whole Message Actions

• Users usually will not need to change the short names.

Styles (Colors)
For each eVC, providers should select a color that will be used when writing the short name of that eVC.
To see all available styles, use vt.show_styles().

For example:
extend vr_ahb_env {
short_name_style(): vt_style is {
return GREEN;
};
};

This will cause two things:

• The word “AHB_1” will be green in the message below:


[10340] AHB_1 M2: Reset is done
• The name of AHB_1 in the show_banner() output (after initial generation) will also appear green.
Usually, users will not need to modify this. However:

• They might decide to change some of the styles to make each eVC unique.
• They might also decide to have the styles go by eVC instance, rather than by eVC type, using
something like:
return (name == AHB_1 ? GREEN : name == AHB_2 ? CYAN : PURPLE);

• They might decide to color each agent separately. That is, they could add a (non-BLACK) style to
M1, M2, and so on. Generally we discourage this, because so many colors might cause a rainbow
effect.

6.10.4 Coloring of Whole Message Actions


By default, the actual text of the message (after the colon) appears black. We recommend that eVC
providers not change that.

However, occasionally, end users or integrators might want to change the message text color. For
example, they might want to color some rare messages so that they will be easier to spot. They can do
that as follows:
set message -style=CYAN "Reset ..."

e Reuse Methodology 6-47


Messaging
Special Tags

6.10.5 Special Tags


Sometimes eVC developers might want to insert special message actions to help a user (or the
developers themselves, remotely) debug a particular algorithm.

For example, the logic for matching scoreboard items might be very complex and unsure. So the
developer could insert message actions like the following:
message(VR_XBUS_SCOREBOARD, HIGH, "Looking for match for ", the_packet) {
print the_packet;
};

This tag would be disabled by default, but it could be enabled when needed.

6.10.6 Tracing Sequences


The trace sequence command issues its messages using message(). Therefore, they come out in the
familiar message format.

These messages use the TRACE_SEQUENCE tag, which is enabled by default in sys.logger.

Using the set message commands, you can write these messages to files, filter them by verbosity, and so
on.

See Also
• “trace sequence” on page 5-67

6.10.7 at_message_verbosity()
There is a global method at_message_verbosity(). Its syntax is:

at_message_verbosity(verbosity: message_verbosity): bool;

The method returns TRUE if you are currently at the specified verbosity (or higher). It might be used as
follows:
extend packet {
do_print() is also {
if at_message_verbosity(HIGH) then {
out("Some more details about this packet:");
out("...");
};
};
};

6-48 e Reuse Methodology


Messaging
Verb Tenses

If you are currently executing a message, at_message_verbosity() uses the verbosity of the current
message logger. Otherwise, it uses the verbosity of sys.logger.

6.10.8 Verb Tenses


We recommend phrasing message in the past tense. For example:
Packet-@3 sent to BFM

Received packet-88

The exception to this is when you want to insert a message before some lengthy operation begins. In that
case you should use the present continuous tense. For example:
message(MEDIUM, "Sending ", packet, " to BFM");
send_to_bfm(packet);

While you can configure loggers in various ways; some standard recommendations follow.

6.10.9 Soft Constraints


We recommend configuring loggers via constraints. Use the procedural or command interface only
when needed. In general, it is better to use soft constraints because you never know if your decisions
might need to be overridden.

6.10.10 sys.logger
We recommend that end users normally use sys.logger.

By default, only LOW verbosity messages go to screen. If end users just want messages at some
verbosity, they can use sys.logger. For example, they might issue the following command:
set message -verbosity=MEDIUM

Of course, they could achieve the same thing via a constraint as follows:
extend sys {keep soft logger.verbosity == MEDIUM};

End users should use the per-eVC and agent loggers only when they need more flexibility (for example,
higher verbosity for one eVC out of many).

6.10.11 When to Issue Message Commands


Normally, we recommend configuring loggers via constraints. However, sometimes you may want to
change the verbosity of some loggers dynamically during runtime.

e Reuse Methodology 6-49


Messaging
When to Issue Message Commands

Note Initially only sys.logger exists. The other loggers get created during the gen phase. Therefore,
until sys is fully generated, only sys.logger should be used.

Following are some typical places to issue set message commands:

• If you are running with a simulator, you can issue set message commands after the test command.
For example:
test
set message -logger=sys.soc1.logger -verbosity=FULL
... // Issue simulator command to run the test here

• Often, you might want to enable messaging only after a specific method has been reached. For
example:
break foo.bar
test
set message -verbosity=FULL
continue

• When running in standalone mode (without a simulator), there is no natural stop before the actual
run. Hence, you can set a breakpoint on sys.run. For example:
break sys.run
test
set message -verbosity=FULL
continue

• Commands that relate only to sys.logger can be issued even before initial generation. These
commands will also carry over after generation. For example, issuing the following command causes
the entire test to run in HIGH verbosity:
set message -verbosity=HIGH
test

• You can configure messaging from within e code, using either:


specman("set message ...")
or via the corresponding API, for example:
extend vr_xbus_env {
run() is also {
logger.set_actions(FULL, {NORMAL}, "*", "...", replace);
-- Sets vr_xbus_env.logger to FULL verbosity
};
};

6-50 e Reuse Methodology


Messaging
Extending message_logger

6.10.12 Extending message_logger


We discourage subtyping message_logger.

While it is possible to define “unit my_logger like message_logger {…}” and instantiate my_logger, in
general we recommend using the original message_logger.

It is acceptable to extend message_logger and change, for example, the format_message() method.

6.10.13 show message -actions


We recommend using show message -actions to find the source of message actions.

The show message -actions command can be used to see what message actions exist in the current
verification environment. This lets you inspect the verification environment and see what it can do.

The show message -actions command also lets you find a specific message action and put a breakpoint
on it. For example, if you want to find the message action that printed “Channel 3 sent a packet” and you
want to stop in the debugger just before it is emitted, you can do the following:

1. Issue the command:


show message -actions "... sent a packet"

2. Click the hyperlink to go to the source.

3. Put a breakpoint there.

6.10.14 Scaling the Time Portion of Message Output


To scale the time portion of your message output to a specified time unit, for example ns, use the
set_config() method. For example:
set_config(print, scale, ns);

or, to use the current Specman time scale:


set_config(print, scale, simdef);

This might cause the printing to look as follows:


[123000 ns] AHB_0 MASTER_1: Received first part of transaction-@33
Note The NULL simulator (the Specman standalone simulator) uses fs as the default time unit.

For more details, see Chapter 12 “Specman Time Scale” in the Specman Elite Integrator’s Guide.

e Reuse Methodology 6-51


Messaging
Scaling the Time Portion of Message Output

6-52 e Reuse Methodology


7 eVC Standardization Using eRM
Compliance Checks
This chapter discusses the requirements for developing a uniform and high-standard eVC. The tables
that follow list the various automatic and non-automatic eRM compliance checks. Automatic checks are
marked with an asterisk (*) after the index item.

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 various compliance rules can be relaxed somewhat for internal packages not intended for general
reuse. Nevertheless, to ensure general plug-and-play and reuse, some compliance checks must be
enforced, even for such internal packages. Those compliance checks are tagged as “eRM-Ready”. The
eRM-Ready checks are marked in the “ER” column of the following tables.

The compliance check tables are:

• “Packaging and Name Space Compliance Checks” on page 7-2


• “Architecture Compliance Checks” on page 7-6
• “Reset Compliance Checks” on page 7-7
• “Checking Compliance Checks” on page 7-9
• “Coverage Compliance Checks” on page 7-10
• “Sequences Compliance Checks” on page 7-10
• “Messaging Compliance Checks” on page 7-12
• “Monitor Compliance Checks” on page 7-13

e Reuse Methodology 7-1


eVC Standardization Using eRM Compliance Checks
Packaging and Name Space Compliance Checks

• “Documentation Compliance Checks” on page 7-13


• “General Deliverables Compliance Checks” on page 7-15
• “Visualization Compliance Checks” on page 7-16
• “End of Test Compliance Checks” on page 7-17
• “Other Possible Compliance Checks” on page 7-17

7.0.1 Packaging and Name Space Compliance Checks


Table 7-1 Packaging and Name Space Compliance Checks

RQ/
RC/ Comments/
Index Check ST ER Information

PKCL Loading with golden eVC— RQ


Does the eVC run properly with the
golden eVC loaded?

PKCT* Configuration template— RQ 3 See “evc/examples/” on page


Are there config templates in the 3-3.
examples directory?

PKDF Valid distribution format— RQ See “Handling Package


Is the package distributed as Versions” on page 2-12.
package_version_version.
tar.gz?

PKDN* Valid ‘define’ name— RQ 3 See “Choosing a Package


Do all ‘define’ names have a legal Name” on page 2-3.
package prefix?

PKDR Demo script running— RQ See “demo.sh File” on page


Does it run OK? 2-8.

PKDS* Demo script availability— RQ See “demo.sh File” on page


Does the package have a demo.sh file to 2-8.
demonstrate the package, located at the
top level of the package?

7-2 e Reuse Methodology


eVC Standardization Using eRM Compliance Checks
Packaging and Name Space Compliance Checks

Table 7-1 Packaging and Name Space Compliance Checks (continued)

RQ/
RC/ Comments/
Index Check ST ER Information

PKEE* Enum extensions— RQ 3


If an enum from some other package is
extended, do the new values start with
the package prefix?

PKEN* Package encapsulation— RQ See “Packages as e Concept”


Does all the code of the eRM package on page 2-2.
belong to one or more e packages (other
than main)?

PKER* Examples documented— RQ See “Examples Directory” on


Is there a EXAMPLES_README.txt page 2-8.
file in the examples directory detailing
the contents?

PKEX* Examples documented—details— RQ See “Examples Directory” on


Are all examples documented? page 2-8.

PKFN* Valid file names— RQ 3 See “File Naming Guidelines”


Do all source code filenames in the on page 3-4.
package start with the package name?

PKGE* Global extends— RC 3


Are there no extends to sys or global?

PKGN* Global extends naming— RQ 3


If sys or global is extended, are the
extensions prefixed with the package
prefix?

PKIM* Import statements— RQ See “Importing Files” on page


Do all import statements refer to 3-7.
imported files using local or
package-relative path?

PKLD* Legal directory name— RQ 3 See “Package-Related Naming


Is the package directory named Conventions” on page 2-3.
consistently with the package name?

e Reuse Methodology 7-3


eVC Standardization Using eRM Compliance Checks
Packaging and Name Space Compliance Checks

Table 7-1 Packaging and Name Space Compliance Checks (continued)

RQ/
RC/ Comments/
Index Check ST ER Information

PKLN* Legal package name— RQ See “Package-Related Naming


Does the package have a legal package Conventions” on page 2-3.
name including company prefix and a
unique intra-company package name?

PKMP* Multiple packages— RQ


If there is more than one e package, do
they all have the same prefix?

PKPN* Package name— RQ See “Choosing a Package


Does the top file belong to an e package Name” on page 2-3.
whose name is identical to the eRM
package?

PKPR* Protection— ST Types and struct


How many public and non-public named members—public and
types and members are there? non-public.

PKSD Simulator support documented— RQ See “PACKAGE_README.txt


Are the simulators supported by the File” on page 2-19.
package documented in the manual?

PKSS Simulator support— RQ See “PACKAGE_README.txt


Are the simulators supported by the File” on page 2-19.
demo documented in the
PACKAGE_README.txt file?

PKTE* Type extensions— RQ 3 See “Choosing a Package


Do all extensions to types defined Name” on page 2-3.
outside the package have fields that start
with legal package prefix?

PKTF Tar file— RQ See “Handling Package


Is the tar file named and organized Versions” on page 2-12.
according to eRM standards?

PKTN* Valid type names— RQ 3 Include types, structs, and


Do all type names have a legal package units.
prefix? See “Choosing a Package
Name” on page 2-3.

7-4 e Reuse Methodology


eVC Standardization Using eRM Compliance Checks
Packaging and Name Space Compliance Checks

Table 7-1 Packaging and Name Space Compliance Checks (continued)

RQ/
RC/ Comments/
Index Check ST ER Information

PKTP* Top file— RQ 3 Check the file has only


Is the top-level file of the eVC placed in imports and defines, and it has
the e subdirectory and called the version definition.
package_top.e? See “e Directory” on page 2-8.

PKVD* Valid directory structure— RQ 3 Is the package's directory


Is the package’s directory structured structured correctly (for
correctly example, e, examples, docs
directories as a minimum)?
See “Directory Structure” on
page 2-5.

PKVN* Version number— RQ 3 Versioning done OK


Does the version number in package version in
PACKAGE_README.txt file match the PACKAGE_README
version number in the top file? version has syntax, 3 levels
(for example, 1.0.2) same
value needs to appear in two
defines:
define VR_XBUS_
VERSION_1_0_2 define
VR_XBUS_VERSION_1_0_
2_OR_LATER version
numbers in all the above.
See “Where the Version
Number Appears” on page
2-12.

PKVR* Valid README file— RQ 3 See “Shipping New Versions of


Is there a legal a Package” on page 2-13.
PACKAGE_README.txt file at the top
level of the package?

e Reuse Methodology 7-5


eVC Standardization Using eRM Compliance Checks
Architecture Compliance Checks

7.0.2 Architecture Compliance Checks


Table 7-2 Architecture Compliance Checks

RQ/
RC/ Comments/
Index Check ST ER Information

ARAA* Active agents— RQ 3 Active agents that contain


Do all ACTIVE agents have a BFM in other agents are not required to
them? have a BFM in them.
See “Agent Types” on page
4-25.

ARAC* Agent names— RQ 3 See “A Look at Agents” on


Do all agents have a “name” field? page 4-6.

ARBF* BFM— RQ 3 “BFM only in active agents”


Are all BFMs instantiated in ACTIVE means: this agent has an
agents? “active_passive” field and the
BFM is instantiated within its
“when ACTIVE” subtype.
See “Sub-Entities” on page
4-24.

ARBS BFM driving signals— RQ 3 See “DUT and eVC” on page


Are all DUT signals driven only by 4-2.
BFMs?

ARHW HW access— RQ 3 See “Terminology” on page


Is all HW access done via signals 4-23.
defined in signal maps or “sig_”
strings?

ARIN* Instantiation— RQ 3 See “DUT and eVC” on page


Are all agents instantiated in envs or 4-2.
other agents?

ARMN* Monitors— RQ 3 See “Modeling FAQs” on page


Are all monitors in envs or agents? 4-22.

ARNM* eVC name— RQ 3 See “Instance Names and IDs”


Does the env have a “name” field? on page 9-6.

7-6 e Reuse Methodology


eVC Standardization Using eRM Compliance Checks
Reset Compliance Checks

Table 7-2 Architecture Compliance Checks (continued)

RQ/
RC/ Comments/
Index Check ST ER Information

ARSA* BFM Sequence drivers in ACTIVE RQ 3 See “A Look at Agents” on


agents— page 4-6.
Are all BFM sequence drivers in
ACTIVE agents?

ARSC Scoreboarding— RC 3 See “Adding Scoreboards” on


Are hooks provided for scoreboarding? page 9-12.

ARSD* ACTIVE agents with BFM sequence RQ 3 Active agents that contain
drivers— other agents are not required to
Do all ACTIVE agents have a BFM have a BFM sequence driver
sequence driver? in them.
See “A Look at Agents” on
page 4-6.

ARSG* Signal definition— RC 3 List the signals defined in


Are there signals (defined in a other units, for example, BFM
signal_map unit or defined with a or monitor.
“sig_” prefix in env or agent units)? See “DUT Signals” on page
4-6.

ARSM* Signal map instantiation— RC See “Components of Agents”


Are there signal maps defined? Are on page 4-8.
they all within agents and env units?

7.0.3 Reset Compliance Checks


Table 7-3 Reset Compliance Checks

RQ/
RC/ Comments/
Index Check ST ER Information

RSCG Clock generator— RQ 3 Qualified and unqualified


Does the package provide a (sufficiently clocks
programmable) clock generator? See “Reset Methodology” on
page 9-2.

e Reuse Methodology 7-7


eVC Standardization Using eRM Compliance Checks
Reset Compliance Checks

Table 7-3 Reset Compliance Checks (continued)

RQ/
RC/ Comments/
Index Check ST ER Information

RSCH Reset checks— RQ 3 See “Reset Methodology” on


Are there sufficient checks to ensure that page 9-2.
the DUT behaves correctly after reset is
de-asserted

RSDC Working with DUT supplied clock— RQ 3 See “Reset Methodology” on


Does the package work with DUT supplied page 9-2.
clock?

RSMR Multiple resets— RQ 3


Does the package manage multiple resets
during the test?

RSPR Programmable resets— RC 3


Does the package provide a mechanism for
generating programmable reset(s) and can
this feature be disabled?

RSRC Multiple reset checks— RQ Name a test that shows


Are there sufficient specific checks relating multiple resets, and a
to the DUT's response to coverage point which
assertion/de-assertion of reset? checks for multiple resets.
See “Supporting Multiple
Resets” on page 9-1.

RSRS Reset support— RQ 3 See “Supporting Multiple


Does the package correctly respond to Resets” on page 9-1.
resets (of any length) generated within the
DUT at the start of the test

RSUC Use of clocks— ST 3 See “Reset Methodology” on


Which parts are running on unqualified page 9-2.
clock?

7-8 e Reuse Methodology


eVC Standardization Using eRM Compliance Checks
Checking Compliance Checks

7.0.4 Checking Compliance Checks


Table 7-4 Checking Compliance Checks

RQ/
RC/ Comments/
Index Check ST ER Information

CHCE* Checks and expects— ST 3


How many checks and expects are there?

CHDE* DUT errors— ST 3


How many dut_errors were defined?

CHDM* DUT error messages— RQ 3


Do all expects and checks have
non-default dut_error message?

CHED Error message documentation— RQ 3 Where in the manual are


Are all checks (both for DUT errors and they documented?
user errors) sufficiently documented?

CHEM Error messages— ST 3


Do all error messages provide sufficient
detail for the user to identify the area and
instance of the package/DUT that
produced the error?

CHEX* Named expects— RC


Are all expects named?

CHPC Protocol checking— RQ 3


Does the package provide sufficient DUT
checking (for example, protocol
checkers) to cover all possible DUT
errors?

CHSC Scoreboard— RC 3 See “Adding Scoreboards”


Does the package provide (where on page 9-12.
appropriate) toolkits to enable the user to
code complex data flow checking tasks
for example, does the package provide a
scoreboard either already integrated, or as
a generic tool?

e Reuse Methodology 7-9


eVC Standardization Using eRM Compliance Checks
Coverage Compliance Checks

7.0.5 Coverage Compliance Checks


Table 7-5 Coverage Compliance Checks

RQ/
RC/ Comments/
Index Check ST ER Information

CVCG* Coverage groups— ST 3


How many coverage groups are
defined?

CVCI* Coverage items— ST 3


How many coverage items are defined?

CVCR* Coverage crosses— ST 3


How many coverage crosses are
defined?

CVRS Coverage results— RQ 3 Preferred approach: Supply


Is the coverage report produced after the ecov files and a shell script
testing this eVC included in the called “show_cover.sh”, all in
package? a directory called
package/ coverage.
Alternative approach: provide
an ASCII coverage report.

7.0.6 Sequences Compliance Checks


Table 7-6 Sequences Compliance Checks

RQ/
RC/ Comments/
Index Check ST ER Information

SQEI Error injection— RQ 3


Do the sequence items provide
sufficient ability to inject errors into the
generated data stream(s)?

SQPT* Predefined sequence types— ST 3 For each SD type, how many


How many predefined sequence types “kinds” of sequences are
are provided? defined in it (other than the 3
default ones), that is, how big
is the sequence library?

7-10 e Reuse Methodology


eVC Standardization Using eRM Compliance Checks
Sequences Compliance Checks

Table 7-6 Sequences Compliance Checks (continued)

RQ/
RC/ Comments/
Index Check ST ER Information

SQRW* Read/Write methods— RC / 3 For SDs that represent


How many sequences have their ST read/write operations, we
read()/write() methods extended? recommend that the
read()/write() of the SD
methods be extended by the
eVC developer.
The report should give
statistics— how many SDs
have extended methods.
See “DUT-Independent
Read/Write Interface” on page
5-41.

SQSD* Subdrivers— RC 3 See “Creating a Virtual


Do all virtual sequence drivers have Sequence” on page 5-26.
subdrivers?

SQSS* SD statistics— ST 3 See “Using Virtual Sequences”


How many sequence drivers exist? on page 5-25.
How many of them are BFM/virtual?

SQVF Error injection—virtual fields— RC 3


Are virtual fields appropriately
employed?

SQVP* Virtual sequence driver (SD) RQ 3 See “Using Virtual Sequences”


pointers— on page 5-25.
Do virtual sequence drivers have
pointers to one or more other sequence
drivers?

SQWR* Read/Write wrappers— ST 3 See “DUT-Independent


How many sequence drivers Read/Write Interface” on page
implement read()/write() methods? 5-41.

e Reuse Methodology 7-11


eVC Standardization Using eRM Compliance Checks
Messaging Compliance Checks

7.0.7 Messaging Compliance Checks


Table 7-7 Messaging Compliance Checks

RQ/
RC/ Comments/
Index Check ST ER Information

MSFL* File loggers— RC See “File Logger(s)” on page


Are there file loggers defined in the 6-44.
package?

MSLC Logger constraints— RC 3 See “Soft Constraints” on page


Are all loggers constrained using only 6-49.
soft constraints?

MSLG* Loggers— RQ See “Screen Logger” on page


Is there a screen logger in the env and 6-44.
in each agent?

MSLI* Logger instantiation— RQ 3 See “Message Loggers” on page


Are all message loggers instantiated in 6-20.
env units, agents monitors or in sys?

MSMA* Message actions— ST 3 See “The Message Action” on


How many message actions are there? page 6-16.
At what verbosity levels are these
actions?

MSMT* Message tags— ST 3 See “message_tag” on page


How many message TAGs were 6-20.
defined?

MSSN* Short name and short name style— RC 3 See


Do short_name() and “any_unit.short_name_style()” on
short_name_style() return page 6-43.
non-empty strings?

7-12 e Reuse Methodology


eVC Standardization Using eRM Compliance Checks
Monitor Compliance Checks

7.0.8 Monitor Compliance Checks


Table 7-8 Monitor Compliance Checks

RQ/
RC/ Comments/
Index Check ST ER Information

MNEE Error extraction— ST 3


For sequence items that collect output
from the DUT, is there a sufficient number
of virtual fields provided to indicate
formatting errors detected in the data
structure?

7.0.9 Documentation Compliance Checks


Table 7-9 Documentation Compliance Checks

RQ/
RC/ Comments/
Index Check ST ER Information

DCBF BFM documentation— RQ


Are all BFMs documented (API and
behavior)?

DCCF Constrainable fields— RQ


Does the documentation describe all
user-constrainable fields and indicate
when they are generated and what
default constraints are applied to them?

DCDC* Documentation— RQ Check /docs directory


Which documentation files exist in the for .doc, .pdf, .fm.
/docs directory (.doc, .pdf)? See “Docs Directory” on page
2-8.

DCEX Examples— RQ
Does the documentation give sufficient
examples to cover the most likely user
scenarios?

e Reuse Methodology 7-13


eVC Standardization Using eRM Compliance Checks
Documentation Compliance Checks

Table 7-9 Documentation Compliance Checks (continued)

RQ/
RC/ Comments/
Index Check ST ER Information

DCFC Features and controls— RQ


Does the documentation cover all
features and controls?

DCFM Documentation format— RC


If the documentation is to be distributed
electronically, does it clearly print both
on color and B&W printers and on both
European A4 and US Letter paper
sizes?

DCID Installation and demo— RQ


Does the documentation describe the
installation and demo processes?

DCPA Package architecture— RQ


Does the documentation describe the
architecture of the package and give an
overview of its intended use?

DCPR Proper documentation— RC


Are concepts introduced before being
referred to?

DCRN* Release notes— RQ Suffix .txt, .pdf, .doc, .rtf.


Are release notes provided in the docs
directory?

DCRP Recommended practice— RQ


Does the documentation clearly
differentiate between what is good and
bad practice when using the package
(for example, which structs should and
should not be extended)?

DCRS Reset— RQ
Does the documentation explain
whether the package manages multiple
resets during the test?

7-14 e Reuse Methodology


eVC Standardization Using eRM Compliance Checks
General Deliverables Compliance Checks

Table 7-9 Documentation Compliance Checks (continued)

RQ/
RC/ Comments/
Index Check ST ER Information

DCSD SD documentation— RQ
Are all sequence-driver test interfaces
sufficiently documented?

DCSP Support policies— RQ


Does the documentation clearly define
the support polices for the package and
indicate contact information for
obtaining support?

DCST eVC structure— RQ


Are diagrams provided to explain the
structure of the eVC? Typical
environments and configurations; how
to use scoreboarding; the class diagram
of the main units and structs.

DCUF Usable fields— RQ


Does the documentation describe all
non-user-constrainable fields that users
may use to control their constraints?

7.0.10 General Deliverables Compliance Checks


Table 7-10 General Deliverables Compliance Checks

RQ/
RC/ Comments/
Index Check ST ER Information

GDCF Customer feedback— RQ


Number of customer engagements this
eVC has been involved in. Provide
customer quotes or feedback indicating
satisfaction level, likes and dislikes if
available.

GDCL* Code lines— ST 3 Statistics with and without


How many lines of code are there? comment lines.

e Reuse Methodology 7-15


eVC Standardization Using eRM Compliance Checks
Visualization Compliance Checks

Table 7-10 General Deliverables Compliance Checks (continued)

RQ/
RC/ Comments/
Index Check ST ER Information

GDNF New functionality— RQ Not applicable for first release,


New functionality added since previous should refer to release notes.
release.

GDNM eVC name RQ As defined in the user manual.

GDPN Protocol name and version— RQ


Name and version number of protocol or
architecture the eVC models.

GDSM Support model— RQ


Description of the post sales support
model for this eVC. (for example,
on-site support for 7 days, then
telephone support).

GDTP Test plan— RQ


Test plan for the eVC and/or a
description of how this eVC was tested
(for example, 5 tests were written and
feedback gathered from 3 beta sites).

7.0.11 Visualization Compliance Checks


Table 7-11 Visualization Compliance Checks

RQ/
RC/ Comments/
Index Check ST ER Information

VT Visualization See “Visualization: Creating


User-Friendly Reports” on page
9-15

7-16 e Reuse Methodology


eVC Standardization Using eRM Compliance Checks
End of Test Compliance Checks

7.0.12 End of Test Compliance Checks


Table 7-12 End of Test Compliance Checks

RQ/
RC/ Comments/
Index Check ST ER Information

ET End of test See “Status Coordination and


End of Test” on page 9-15.

7.0.13 Other Possible Compliance Checks


Table 7-13 Other Possible Compliance Checks

RQ/
RC/ Comments/
Index Check ST ER Information

Code Structure

Coding Style

Test Interface

e Reuse Methodology 7-17


eVC Standardization Using eRM Compliance Checks
Other Possible Compliance Checks

7-18 e Reuse Methodology


8 The eRM Utility
The eRM Utility lets you:

• Browse eRM packages, load them, run their demo, and so on


• Browse the Unit and Env structure of the verification environment
• View eRM sequence stripe charts
• Control messages and message loggers
• Generate eDoc reports

To launch the eRM Utility:

• In Specview, click the eRM button .

The eRM Utility main window opens (see Figure 8-1).

Note The toolbar at the top of each eRM Utility window lets you navigate to the other windows.

e Reuse Methodology 8-1


The eRM Utility

Figure 8-1 eRM Utility Main Window

The chapter explains how to use the eRM Utility. It contains the following sections:

• “Browsing eRM Packages” on page 8-3


• “Examining Envs and Units” on page 8-5
• “Controlling Messaging” on page 8-16
• “Using the eDoc Tool” on page 8-21

8-2 e Reuse Methodology


The eRM Utility
Browsing eRM Packages

8.1 Browsing eRM Packages


Figure 8-2 eRM Packages Loaded Window

To browse the loaded eRM packages:

• In the eRM Utility, click the Loaded button .

The eRM Packages Loaded window (see Figure 8-2) opens with a list of all loaded eRM packages. Each
package in the list is a hyperlink to the eRM Package window for that package (see “The eRM Package
Window” on page 8-5).

e Reuse Methodology 8-3


The eRM Utility
Browsing eRM Packages

Figure 8-3 eRM Packages on Disk Window

To browse all eRM packages on disk:

• In the eRM Utility, click the On Disk button .

The eRM Packages on Disk window (see Figure 8-3) opens with a list of all packages on disk, by library,
whether loaded or not. Each package in the list is a hyperlink to the eRM Package window for that
package (see “The eRM Package Window” on page 8-5).

8-4 e Reuse Methodology


The eRM Utility
The eRM Package Window

8.1.1 The eRM Package Window


Figure 8-4 eRM Package Window

The eRM Package window shows the details about a package (title, version, and so on).

Clicking the README button displays the package readme file.

Clicking the directory hyperlink lets you examine the package files.

For loaded packages, there is an eDoc button that takes you to the eDoc window. This shows
auto-extracted documentation for the eRM package. (For more information, see “Using the eDoc Tool”
on page 8-21.)

For non-loaded packages, there is an option to activate the @demo.ecom of that package if it exists and
to activate the demo.sh of that package (in another window) if it exists.

Note Avoid running more than one @demo.ecom in the same Specview window. If you want to run
another demo in the same window, do a restart before activating the new demo script.

8.2 Examining Envs and Units


Once a package is loaded, you can browse the instantiated envs or the unit tree.

e Reuse Methodology 8-5


The eRM Utility
Examining Envs and Units

Figure 8-5 Env Tree Window

To browse the instantiated envs:

• In the eRM Utility, click the Envs button .

The Env Tree window (see Figure 8-5) opens with a hierarchical list of all instantiated envs. Clicking an
env hyperlink opens that env in the Specman Data Browser. Clicking the Visualize button next to an env
opens the Env window for that env (see “The Env Window” on page 8-8).

8-6 e Reuse Methodology


The eRM Utility
Examining Envs and Units

Figure 8-6 Unit Tree Window

To browse the unit tree:

• In the eRM Utility, click the Units button .

The Unit Tree window (see Figure 8-6) opens with a hierarchical list of all units under sys. Clicking a
unit hyperlink opens that unit in the Specman Data Browser. Clicking the Visualize button next to an env
unit opens the Env window for that env (see “The Env Window” on page 8-8).

Notes
• If you view the Env Tree or Unit Tree window before generation, there are no instantiated envs.
Therefore, you see only a Generate button. Clicking the Generate button generates the environment
and refreshes the window.

e Reuse Methodology 8-7


The eRM Utility
The Env Window

• If a unit has short_name() and short_name_style() defined for it, then the name and color are used
for that unit. (For information on setting the name and color, see “The short_name_path() of a Unit”
on page 6-40 and “Colors for Message Actions” on page 6-42.)

8.2.1 The Env Window


Figure 8-7 Env Window

This window shows the basic information of the env (package name, title, HDL path, and so on),
followed by a list of the drivers in the env (for stripe-chart visualization), and finally followed by the
unit tree of the env. The eVC provider can customize the content of this window (see “Customizing
Visualization” on page 8-11).

8-8 e Reuse Methodology


The eRM Utility
The Stripe Chart Window

From the Env window, you can go to the eDoc Report window by clicking the eDoc button. The eDoc
Report window shows auto-extracted documentation for that env. For more information on eDoc
reports, see “Using the eDoc Tool” on page 8-21.

From the Env window, you can display stripe charts for one or more sequence drivers by selecting the
desired drivers in the Stripe Chart list and clicking the Show button. For more information on stripe
charts, see “The Stripe Chart Window” on page 8-9.

8.2.2 The Stripe Chart Window


Figure 8-8 Stripe Chart Window (Single-Stream)

e Reuse Methodology 8-9


The eRM Utility
The Stripe Chart Window

This window is opened via the Show button in the Env window. It shows a stripe chart for one or more
input or output streams (usually sequence drivers). It displays each sequence and sequence item, sorted
by start time. The indentation shows the sequence hierarchy.

The hyperlinks in the stripe charts lead to the source code and the data browser for additional
information related to the sequence. The “tree” hyperlink displays the selected object in a tree view,
from which you can browse all subsequences and parent sequences.

For information on customizing the display of stripe charts, see “Customizing Visualization” on page
8-11.

Figure 8-9 Stripe Chart Window (Multi-Stream)

8-10 e Reuse Methodology


The eRM Utility
Customizing Visualization

Multi-stream charts have each stream indented at a different level.

Figure 8-10 Stripe Chart Window (Tree)

The tree view starts with a single stripe. The tree hyperlinks (at the left end) let you expand all
subsequences (by clicking the plus “+”) or parent sequences (by clicking the caret “^”).

8.2.3 Customizing Visualization


eVC developers can customize the Env and the Stripe Chart windows of their eVC in various ways.

To see an example of customized visualization for the vr_xbus eVC:

1. Run vr_xbus/demo.sh.

2. Rather than doing the normal load, in the Specview window, enter:
@vt_util/examples/vr_xbus_visualization

3. From the User menu in Specview, choose “eRM Utility” to see the customized window of the env.

e Reuse Methodology 8-11


The eRM Utility
Customizing Visualization

4. Issue the test command and run the test as usual.

5. Go back to the vr_xbus Env window, and browse through the (now updated) stripe charts.

You can see how the customization was done by examining vt_util/examples/vr_xbus_visualization.e.
The HTML template used is vt_util/examples/vr_xbus_template.html.

Note By default, sequence stripes are disabled to reduce overhead. In other words the eRM Utility does
trace sequence off, and therefore the sequence stripes are empty. To enable sequence information in
stripe charts, issue the trace sequence log_only command.

This section explains how to customize the Env and the Stripe Chart windows. It contains:

• “Changing the Visualized Information in the Env Window” on page 8-12


• “Changing the HTML Template for the Env Window” on page 8-13
• “Adding Information to the Stripe” on page 8-13
• “Showing User-Defined Items as Stripes” on page 8-14
• “Showing Sub-Items as Stripes” on page 8-14
• “Customization-Related Methods” on page 8-15

8.2.3.1 Changing the Visualized Information in the Env Window


The Env window automatically shows information taken from the eVC. By default, the information is
presented in 3 levels:

1. Basic information This information is returned as a list of string by the method


(name, version, and so on) any_env.get_env_basic_info()
2. Stripe chart This information is returned as a list of string by the method
any_env.get_env_stripe_chart_info()
3. Unit tree This information is returned as a list of string by the method
any_env.get_env_detailed_info()

To change the visualized information in the Env window:


• Override any one of the three aforementioned methods to present your own env information.
For example, you could add information about the current state of your env (like the number of packets
transferred) as follows:
extend vr_xbus_env_u {
get_env_basic_info() : list of string is also {
// Add HTML text to report on...

8-12 e Reuse Methodology


The eRM Utility
Customizing Visualization

};
};

8.2.3.2 Changing the HTML Template for the Env Window


The structure and appearance of the Env window is determined by an HTML template that you can
customize. The default template is vt_util/e/vt_util_env_template.html. We recommend making all
changes to the HTML template in a separate file.

To change your HTML template for the Env window:


• Extend the visualize() method to call another HTML template file.
For example:
extend vr_xbus_env_u {
visualize() is only {
vt_util.show_html_file (vt.template_to_html
("vt_util/examples/vr_xbus_template.html"));
};
};

8.2.3.3 Adding Information to the Stripe


For any data item (inherited from any_sequence_item) the stripe() method is defined in the VT package
as follows:
stripe(s : vt_stripe) is {
get_stripe_prefix(s);
get_stripe_body(s);
get_stripe_suffix(s);
};

To add information to the stripe:


• Extend the method get_stripe_body(s), which is empty by default.
For example, you could add five cyan-colored boxes showing the most interesting fields in an XBus
transfer as follows:
extend vr_xbus_trans_s {
get_stripe_body(s : vt_stripe) is only {
s.add_divider();
s.add_box("kind",kind ,CYAN);
s.add_box("addr", addr,CYAN);
s.add_box("data",data,CYAN);
s.add_box("direction",read_write ,CYAN);

e Reuse Methodology 8-13


The eRM Utility
Customizing Visualization

s.add_box("size",size,CYAN);
};
};

8.2.3.4 Showing User-Defined Items as Stripes


The eRM Utility automatically knows how to show stripe charts of sequences sent by sequence drivers.
However, you can also show stripes for any other data items that inherit from any_sequence_item (for
example, data items collected by your monitor).

To show user-defined data items as stripes:


• Call the any_sequence_item.create_visual_stripe() method.
This method adds the relevant data item to a list in the vt_util and also updates its start_time. For
example:
extend vr_xbus_bus_monitor_u {
on data_start {
if transfer != NULL {
transfer.create_visual_stripe(
me,"xbus monitor", sys.time);
};
};
};
Note If you want to update the end_time, you must use any_sequence_item.end_visual_stripe().

8.2.3.5 Showing Sub-Items as Stripes


Sometimes, sequence items hold sub-items that are not sent through a sequence driver but still inherit
from any_sequence item. For example, assume that you have x_burst items. In other words, you
generate sequences of x_burst. At the same time, each x_burst contains a list of x_transfer. In that case,
x_transfer will not be shown automatically in the stripe charts as a child of x_burst.

To show sub-items (not sent through a sequence driver) as stripes:


• Extend the any_sequence_item.get_trace_list() method. For example:
extend MONITOR vr_zserial_frame_s {
get_trace_list() : list of any_sequence_item is {
result.add(payload);
};
};

8-14 e Reuse Methodology


The eRM Utility
Customizing Visualization

8.2.3.6 Customization-Related Methods

Return
Method Description Parameters Value
Methods of any_sequence_item

get_stripe_prefix() Adds default implementation for s: vt_stripe


stripe prefix.

get_stripe_body() Extended by the user to customize the s: vt_stripe


stripe chart.

By default, this method is empty.

get_stripe_suffix() Adds default implementation for s: vt_stripe


stripe suffix.

stripe() Calls get_stripe_prefix(), s: vt_stripe


get_stripe_body(), and
get_stripe_suffix() to convert data
item info into stripe info.

create_visual_stripe() Adds user-defined data items (for caller:


example, monitor items) to a list of any-struct
items that can be shown as stripes.
The particular list is determined by name: string
the given name. If the name is empty, t: time
the caller e_path() or to_string() is
treated as the name.

Also, updates an internal field that


can later be shown as the start time of
the stripe.

end_visual_stripe() Updates the end time for the stripe. t: time

get_trace_list() Returns the list of items or sequences list of any_


that were directly called by the sequence_
sequence. item
Methods of any_env

get_env_basic_info() Shows basic information in the Env list of string


window.

get_env_detailed_info() Shows unit tree in the Env window. list of string

e Reuse Methodology 8-15


The eRM Utility
Controlling Messaging

Return
Method Description Parameters Value

get_env_stripe_chart_ Shows stripe chart information in the list of string


info() Env window.

8.3 Controlling Messaging


The eRM Utility provides various windows to facilitate control over messaging (see Table 8-1).

Table 8-1 eRM Utility Messaging Windows

Window Description Figure

Message Loggers Shows basic information for each message Figure 8-11 on page
logger with hyperlinks to each message logger’s 8-17
individual Message Logger window.

Message Logger Shows detailed information for a specific Figure 8-12 on page
message logger and lets you make on-the-fly 8-18
changes to that logger’s settings for recognized
message tags.

Logger Destinations Lists all available message destinations, showing Figure 8-13 on page
for each its associated loggers. The logger 8-19
hyperlinks open the relevant Message Logger
window.

Messages Lists all messages with details on verbosity, tag, Figure 8-14 on page
logger, and package. The message hyperlinks 8-20
display the source code for that message.

This section contains:

• “Controlling Message Loggers” on page 8-17


• “Controlling Messages” on page 8-20

See Also
• Chapter 6 “Messaging”

8-16 e Reuse Methodology


The eRM Utility
Controlling Message Loggers

8.3.1 Controlling Message Loggers


Figure 8-11 Message Loggers Window

The Message Loggers window (Figure 8-11) lists all message loggers. Clicking a logger hyperlink takes
you to a Message Logger window for the specified logger (Figure 8-12) where you can make on-the-fly
changes to the settings for recognized message tags and verbosity.

To open the Message Loggers window:

• In the eRM Utility main window, click the Msg button .

The Message Loggers window (Figure 8-11 on page 8-17) opens in a new window.

e Reuse Methodology 8-17


The eRM Utility
Controlling Message Loggers

Tip Clicking the Loggers button in an eRM Utility messaging window also opens the Message
Loggers window (Figure 8-11).

Figure 8-12 Message Logger Window

In the Message Logger window for a particular logger (Figure 8-12), you can change the verbosity for a
message tag, remove tags from the message logger, and change the logger’s message format.

To change the verbosity for a message tag:


• Select the tag and the desired verbosity from the drop-down menu and click Set.

8-18 e Reuse Methodology


The eRM Utility
Controlling Message Loggers

To remove a tag from the logger:


• Select the tag from the drop-down menu and click Remove.

To change the message format:


• Select the desired format from the drop-down menu and click Set.

8.3.1.1 The Logger Destinations Window


Figure 8-13 Logger Destinations Window

The eRM Utility also has a Logger Destinations window that lists all possible logger destinations with
their associated loggers. The logger hyperlinks display the corresponding logger window (see Figure
8-12).

To open the Logger Destinations window:

• In any eRM Utility messaging window, click the Destinations button .

The Logger Destinations window opens in a new window.

e Reuse Methodology 8-19


The eRM Utility
Controlling Messages

8.3.2 Controlling Messages


Figure 8-14 Messages Window

This Messages window (Figure 8-14) lists all messages with details on verbosity, tag, logger, and
package. The message hyperlinks display the source code for that message.

To open the Messages window:

• In any eRM Utility messaging window, click the Messages button .

The Messages window opens in a new window.

8-20 e Reuse Methodology


The eRM Utility
Using the eDoc Tool

8.4 Using the eDoc Tool


eDoc is an automatic documentation tool for capturing the structure of an e package or module.

eDoc reports consist of tables of fields, methods, and events for all units, structs, and sequences at the
specified level of encapsulation. In addition, sequences also have tables of their subtypes.

At the beginning of each report is a summary of all structs. At the end of each report is a table of all
user-defined types.

This section explains how to generate eDoc reports. It contains:

• “The eDoc Window” on page 8-22


• “Generating eDoc Reports” on page 8-23
• “show doc” on page 8-24

e Reuse Methodology 8-21


The eRM Utility
The eDoc Window

8.4.1 The eDoc Window


Figure 8-15 eDoc Window

The eDoc window (Figure 8-15) lets you select the package or individual files and automatically
generate an eDoc report (see “Generating eDoc Reports” on page 8-23) from the source code.

To launch the eDoc tool:

• In the eRM Utility, click the eDoc button .

The eDoc tool opens in a new eRM Utility window.

8-22 e Reuse Methodology


The eRM Utility
Generating eDoc Reports

8.4.2 Generating eDoc Reports


Figure 8-16 eDoc Report Window

The information for the eDoc report (Figure 8-16) is collected from the code of a loaded package or
module. For each unit, struct, and sequence, eDoc can collect all fields, events, and methods with their
in-line documentation.

Comments above the code line or at the end of the line are collected into the description field for the
item. All information is concatenated into a single string that fits in a single table cell. HTML formatting
can be used for HTML output, for example, <br> for new line.

e Reuse Methodology 8-23


The eRM Utility
show doc

To generate documentation for a package:


• In the eDoc window, select the package and/or files for which you want to generate a report and then
click Create.

eDoc generates a report and opens it in an eDoc Report window (Figure 8-16).

The Structs table in the eDoc report contains hyperlinks to the tables relating to the selected struct
(fields, methods, and events). Struct members have hyperlinks to the source code where they are
defined.

8.4.3 show doc


You can use the show doc command from the vrst-tool> prompt to generate eDoc reports for loaded
packages and modules.

Purpose
Generate an eDoc report

Category
Command

Syntax
show doc [-l[oad[_order]] -net[scape]] [-public] [-protected] [-package] [-private]
package_name|@modules

Syntax Examples
show doc vr_xbus

This displays an HTML report for the vr_xbus package in the VT window. You get the same result when
you click the eDoc button in the VT window for the vr_xbus package.
show doc -net -public -protected @vr_ahb*

This displays an HTML report in Netscape for all public and protected fields, events, and methods of
modules with names beginning with “vr_ahb”.

Parameters

-load_order Sort report by order of loading. (The default is alphabetical order.)

8-24 e Reuse Methodology


The eRM Utility
show doc

-netscape Display an HTML report in a Netscape browser window. (The default is to


display in a VT window.)

-public Show all fields, methods, and events with encapsulation “public”. (If no
encapsulation option is specified, then this is the default. If any encapsulation
option is specified, then public is displayed only when specified.)

-protected Show all fields, methods, and events with encapsulation “protected”.

-package Show all fields, methods, and events with encapsulation “package”.

-private Show all fields, methods, and events with encapsulation “private”.

package_name Package to be analyzed.

@modules Modules to be analyzed, for example, “@vr_xbus*”.

Description
You can display eDoc HTML reports in either the VT window (the default) or in a Netscape browser
window with a sort order that is either alphabetical or chronological (based in respect to loading). You
can specify the level of encapsulation for the fields, methods, and events to be reported. Reports can be
generated for packages or modules. Wildcards are accepted.

e Reuse Methodology 8-25


The eRM Utility
show doc

8-26 e Reuse Methodology


9 Reference
This chapter provides a more detailed discussion of various related topics.

• “Supporting Multiple Resets” on page 9-1


• “Instance Names and IDs” on page 9-6
• “Adding Scoreboards” on page 9-12
• “Visualization: Creating User-Friendly Reports” on page 9-15
• “Status Coordination and End of Test” on page 9-15
• “Encrypting Packages” on page 9-25

9.1 Supporting Multiple Resets


This section includes:

• “Reset Assumptions and Requirements” on page 9-1


• “Reset Methodology” on page 9-2
• “rerun()” on page 9-4
• “Reset Example” on page 9-5

9.1.1 Reset Assumptions and Requirements

9.1.1.1 Primary Requirements


For multiple resets of the DUT in tests:

e Reuse Methodology 9-1


Reference
Reset Methodology

• Temporals: Graceful shutdown / rerun (events, expects, TCMs)


• Data and State: Smooth resetting of vars, scoreboard, and so on
• Monitors: No false coverage information, no missed DUT errors, no coverage errors
• Agents: No protocol violations

9.1.1.2 Secondary Requirements


• Allow reset initiated by DUT or by eVC
• Easy/flexible hooks for users to do what they want upon reset (for example, drive chosen reset values
into signals during reset)

9.1.2 Reset Methodology


In 3.x, supporting reset required complicated mechanisms. Verisity eVCs supported only one reset in a
test.

In 4.x, a new predefined method rerun() (see “rerun()” on page 9-4) is defined for units and structs in e.
It manages termination and restart of TCMs and temporals during reset.

Figure 9-1 New Reset Methodology

9-2 e Reuse Methodology


Reference
Reset Methodology

The current reset methodology works as follows:

• There are two main reset events:


• @reset_start— Signifies the point in time reset becomes visible to the DUT.
• @reset_end— Signifies the point in time reset no longer is affected the DUT.

• There are two main clock events:


• @clk— Ticks only when there is no reset. Most temporals and TCMS should use this clock, and
thus they pause during reset.
• @unqualified_clk— Ticks all the time, including during reset. This is used for TCMs and
checkers that continue their work throughout reset.

• The env is immune to reset.


• It might have parts that run on the unqualified clock and check specifically the reset-related
behavior.
• Agents are affected by reset.
• Each agent identifies its own reset independently.
• Agents should propagate rerun() recursively to sub-units.
• Most TEs and TCMs use the qualified clock (@clk).
• This makes them sleep until reset is over.
Notes
• The following four reset events are of interest, because they allow finer granularity and hooks to
specify delay between reset assertion/deassertion and the time it is noticed by the DUT.
• reset_start, reset_end— Main events, signifying the DUT notices reset change
• reset_asserted, reset_deasserted— Precise @sim events
• In multiple clock DUTs (or if clock_rise and clock_fall are used), each clock needs a qualified and
an unqualified version.
• Most of the eVC state must be reset, but not all of it.
• Memory areas often need to keep content.
• Reset controlling and checking needs to continue unharmed.

e Reuse Methodology 9-3


Reference
rerun()

• Be careful regarding race conditions (for example, if reset is asserted at a clk cycle and @clk and
@reset_started are both active). Particular care must be taken when one eVC wants to send reset to
another eVC. To enable that:
• Ideally, eVC-1 drives some HW signals that eVC-2 is sensitive to. Thus reset is sensed by eVC-2.
• If reset is initiated by another e component and you want to do it all in e, do that by calling
rerun(), not by emitting an event.
• rerun() is less prone to races, because it schedules the quit() to be done as the last thing of the
specman tick, and the run() to be done as the first thing of the next Specman cycle.
Note Specman tick refers to the current call to specman_tick(). The next Specman cycle is a
call to specman_tick that has a new sys.time.

9.1.3 rerun()

Syntax
[instance-exp.]rerun()

Syntax Example
master.rerun();

Description
The rerun() method:

• Deactivates a struct/unit instance at the end of tick by calling quit(). This kills all TCMs, events, and
expects of the instance.
• Reactivates the instance at the beginning of the next tick by calling its run() method. This activates
the events and expects of the instance.

Note
• rerun() of an instance does not call the rerun() of its children recursively. The same is true for quit().

9-4 e Reuse Methodology


Reference
Reset Example

Figure 9-2 Reset Timing

9.1.4 Reset Example

extend xyz_env { 1. Define clocks.


event unqualified_clk is change('(sig_clock)') @sim;1
event clk is
true('(sig_reset)'==DEASSERTED) @unqualified_clk;
};

extend xyz_env { 2. Define reset


event reset_start is fall('(sig_reset)') @sim; events.
event reset_end is rise('(sig_reset)') @sim;
};

extend xyz_agent2 { 3. Propagate


rerun()
on reset_start1 { recursively.
rerun();
};

rerun() is also {
-- If my_sub_structs is a list of structs under xyz_agent...
for each (s) in my_sub_structs {
s.rerun();
};
};
};

e Reuse Methodology 9-5


Reference
Instance Names and IDs

extend xyz_agent { 4. Define agent


main() @clk is {...}; // main TCM activity: TCMs and
run() is also { TEs that halt on
start main(); reset.
};
};
extend xyz_agent_monitor {
event data_phase is {@arb_phs; @addr_phs}@clk;
expect true('(sig_start)' == 0) @data_phase;
};

extend xyz_env_monitor { 5. Reset checker:


expect @reset_start => TEs that
{[3] * not @reset_end} @unqualified_clk; continue on reset.
};

1. Immune to reset (unqualified clock)

2. Subject to reset (qualified clock)

9.2 Instance Names and IDs


This section includes:

• “About Instance Names and IDs” on page 9-6


• “Enumerated Logical Names” on page 9-7
• “Scalar IDs” on page 9-8
• “Use of Instance Names and IDs” on page 9-8
• “Instance Names: XBus Example” on page 9-9

9.2.1 About Instance Names and IDs


An important feature of the user interface of an eVC is the user’s ability to separately constrain
individual instances of structs and units within the eVC. This becomes particularly important for main
units of the eVC such as envs and agents.

Users can of course achieve this with the absolute path from sys to the instance. For example:
extend sys {
keep my_environment.my_evc_instance_a.masters[3].speed == 5;
};

9-6 e Reuse Methodology


Reference
Enumerated Logical Names

However, this is not a particularly user-friendly interface. Giving each instance a logical name or ID
results in a far more powerful interface. The logical name or ID can be used in constraints within the
struct or unit to achieve differentiated behavior between different instances.

There are two methods of providing this functionality: Enumerated Logical Names and Scalar IDs.
Where practical, we recommend the Enumerated Logical Names approach.

9.2.2 Enumerated Logical Names


Ideally it should be possible to subtype the struct or unit on the logical name. To do this, the name must
be specified as an enumerated type. The eVC developer should create an enumerated type (normally this
will be initially empty) and a field in the struct or unit of that type. We recommend calling this field
“name”.

Each time users want to create a new instance of the struct or unit, they must extend the enumerated type
to create a new logical name and then create an instance of the struct or unit that has its name field
constrained to the new logical name. For example:

eVC Developer File


type my_evc_env_name_t : []; // initially empty

unit my_evc_env_u like any_env {


name : my_evc_env_name_t;
speed : uint;
...
};

User Configuration File


extend my_evc_env_name_t : [INSTANCE_A];

extend sys {
my_evc_a : my_evc_env_u is instance;
keep my_evc_a.name == INSTANCE_A;
};

With this approach, users can then subtype the struct or unit using the logical name to apply constraints
to a specific instance. For example:
extend INSTANCE_A my_evc_env_u {
keep speed == 5;
};

e Reuse Methodology 9-7


Reference
Scalar IDs

Note It is possible to have multiple instances of a struct or unit with the same logical instance name.
Constraints applied to the subtype of the struct or unit will then apply to all instances with that logical
instance name. This lets users create a group of instances that have identical behavior.

9.2.3 Scalar IDs


In some cases, it does not make sense for users to have to create a logical name in order to create an
instance—for example, where the eVC automatically creates a large number of instances. In such cases,
it may be appropriate for instances to be identified by an ID field of an appropriate scalar type. We
recommend calling the ID field “id”. For example:

eVC Developer File


unit my_evc_agent_u {
id : uint;
port_name : string;
...
};

extend my_evc_env_u {
agents : list of my_evc_agent_u is instance;
keep for each (agent) in agents {
agent.id == index;
};
};
Note Use of a scalar ID means that the struct or unit cannot be subtyped. However, the ID can still be
used to control constraints in extensions of the base type. For example:
extend my_evc_agent_u {
keep id == 5 => port_name == “PORT_A”;
};

9.2.4 Use of Instance Names and IDs


Instance names and IDs can be used for:

• Constraining behavior (configuration and tests)


• Extending sequences
• Debugging and printing
• Coverage per instance

9-8 e Reuse Methodology


Reference
Instance Names: XBus Example

We recommend giving all major units in an eVC a logical name or ID field (for example the top level
env unit, the agent unit, and so on).

Moreover, it often helps for data structs to have fields that indicate the logical name or ID of the unit by
which they were generated. For example, a packet struct might have a field indicating the logical name
of the agent that generated it. This lets users constrain fields within the data struct according to the agent
that generates it.

eVC Developer File


struct my_evc_packet_s {
agent_name : my_evc_agent_name_t;
packet_delay : uint;
...
};

User Test File


// All packets generated by AGENT_A should have a delay of 5
extend AGENT_A my_evc_packet_s {
keep packet_delay == 5;
};
Note While it is possible to constrain the data struct’s agent_name field with get_enclosing_unit(), we
recommend that this field be constrained by the unit that generates the struct at the point of generation.
This results in code that is less susceptible to problems arising from unforeseen reuse.

9.2.5 Instance Names: XBus Example


The following example shows the recommended approach to providing logical instance names for a
typical eVC. The example shows how the instance name fields are created and how a user interface for
creating eVC configurations can be built around instance names. This code is a simplified form of that
found in the XBus Golden eVC (the vr_xbus package of erm_lib).

This section includes:

• “eVC Developer Files” on page 9-9


• “eVC User Files” on page 9-11

9.2.5.1 eVC Developer Files

vr_xbus_types.e
type vr_xbus_agent_name_t : [];

e Reuse Methodology 9-9


Reference
Instance Names: XBus Example

type vr_xbus_bus_name_t : [];

vr_xbus_agent.e
unit vr_xbus_agent_u {
name : vr_xbus_agent_name_t;
};

vr_xbus_env.e
unit vr_xbus_env_u like any_env {
name : vr_xbus_bus_name_t;
agent_names : list of vr_xbus_agent_name_t;
keep soft agent_names.size() == 0;
agents : list of vr_xbus_agent_u is instance;
keep agents.size() == agent_names.size();
keep for each (agent) in agents {
agent.name == agent_names[index];
};
};

vr_xbus_trans.e
struct vr_xbus_trans_s like any_sequence_item {
agent_name : vr_xbus_agent_name_t;
};

vr_xbus_sequence.e
sequence vr_xbus_sequence using
item = vr_xbus_trans_s,
created_driver = vr_xbus_driver_u;

extend vr_xbus_driver_u {
agent_name : vr_xbus_agent_name_t;
};

extend vr_xbus_sequence {
agent_name : vr_xbus_agent_name_t;
keep agent_name == driver.agent_name;
// For "do trans"
!trans: vr_xbus_trans_s;
keep trans.agent_name == agent_name;
};

extend vr_xbus_agent_u {

9-10 e Reuse Methodology


Reference
Instance Names: XBus Example

sequence_driver: vr_xbus_driver_u is instance;


keep sequence_driver.agent_name == name;
};

vr_xbus_coverage.e
extend vr_xbus_trans_s {
event trans_done;
cover trans_done is {
item name : vr_xbus_agent_name_t = agent_name
};

9.2.5.2 eVC User Files

vr_xbus_config.e
extend vr_xbus_bus_name_t : [NORTH_XBUS, SOUTH_XBUS];
extend vr_xbus_agent_name_t : [AGENT_N_A, AGENT_N_B,
AGENT_S_A];
extend sys {
xbus_north : NORTH_XBUS vr_xbus_env_u is instance;
xbus_south : SOUTH_XBUS vr_xbus_env_u is instance;
};
extend NORTH_XBUS vr_xbus_env_u {
keep agent_names == {AGENT_N_A; AGENT_N_B};
};
extend SOUT_XBUS vr_xbus_env_u {
keep agent_names == {AGENT_S_A};
};
extend AGENT_N_A vr_xbus_agent_u {
keep min_addr == 0x0000; keep max_addr == 0x7fff;
};
extend AGENT_N_B vr_xbus_agent_u {
keep min_addr == 0x8000; keep max_addr == 0xffff;
};
extend AGENT_A_A vr_xbus_agent_u {
keep min_addr == 0x0000; keep max_addr == 0xffff;
};

Test_1.e
extend AGENT_N_A MAIN vr_xbus_master_sequence {
body() @driver.clock is only {
write(1, 0x0, 0xff);
};

e Reuse Methodology 9-11


Reference
Adding Scoreboards

};
extend AGENT_N_B MAIN vr_xbus_master_sequence {
body() @driver.clock is only {
write(1, 0x8000, 0xff);
};
};
extend AGENT_S_A MAIN vr_xbus_master_sequence {
keep sequence.kind.reset_soft();
keep soft sequence.kind == select {
90 : SEQUENCE_A;
10 : SEQUENCE_B;
};
};

9.3 Adding Scoreboards


This section includes:

• “What Is a Scoreboard?” on page 9-12


• “Memory Access Scoreboards” on page 9-13
• “End-to-End Scoreboards” on page 9-13
• “End-to-End Scoreboard Hooks” on page 9-13
• “Scoreboard Recommendations” on page 9-14

9.3.1 What Is a Scoreboard?


• Scoreboards are a form of reference model.
• They model memory based devices (RAM, FIFO, and so on) and data mover devices (routers,
bridges, and so on).
• They can be extended with algorithmic calculation to form a more complex reference model.
• There are two main types of scoreboard:
• Memory access scoreboards
• End-to-end scoreboards:
– Homogeneous
– Heterogeneous
• A simple scoreboard is just a list, but may include more complexity.

9-12 e Reuse Methodology


Reference
Memory Access Scoreboards

9.3.2 Memory Access Scoreboards


• Models RAM within the DUT.
• Typically uses sparse RAM model.
• All writes to DUT RAM are logged in scoreboard.
• All reads from DUT RAM are checked against scoreboard.
• Might need to handle destructive reads, and so on, for some DUTs.
• Can also be used to ensure tests are only read from locations already written to.

9.3.3 End-to-End Scoreboards


• Models ‘data mover’ type DUT (for example, FIFO).
• Two ends of scoreboard may not be connected to the same eVC.
• Where to instantiate scoreboard...
• Under source agent?
• Under destination agent?
• Under sys?
• Leave it up to the user!
• When to add/remove items to/from the scoreboard?
• Leave this for the user to decide as well.
• eVCs should include standard hooks.

9.3.4 End-to-End Scoreboard Hooks


The most common method is to provide user-extensible method. For example:
// eVC hook - gets called each time an agent completes a
// transfer.
extend vr_xbus_agent_u {
transfer_completed(transfer : vr_xbus_trans_s) is empty;
};
// user hookup
extend BRIDGE_SIDE_A_SLAVE vr_xbus_agent_u {
transfer_completed(transfer : vr_xbus_trans_s) is also {
sys.my_scrbd.add_item(transfer);

e Reuse Methodology 9-13


Reference
Scoreboard Recommendations

};
};

extend BRIDGE_SIDE_B_MASTER vr_xbus_agent_u {


transfer_completed(transfer : vr_xbus_trans_s) is also {
sys.my_scrbd.check_and_remove_item(transfer);
};
};
Note Care must be taken to ensure that the user does not alter data structures vital to the correct
working of the eVC.

In some cases, users will not be able to subtype the eVC agent to extend a method. We need to provide
parallel mechanism that does not require subtyping.
// eVC hook
extend vr_xbus_agent_u {
current_transfer : vr_xbus_trans_s;
event transfer_complete;
};
// User code e.g.
event transfer_sent is
@sys.my_evc.my_agent.transfer_complete;
on transfer_sent {
sys.my_scrbd.add_item(sys.my_evc.my_agent.current_transfer);
};

9.3.5 Scoreboard Recommendations


• Memory access scoreboards:
• Scoreboard should be instantiated within eVC shadow agent.
• Hookup should be largely automatic.
• End-to-end scoreboards:
• Scoreboard hooks should be placed wherever appropriate in each eVC (both as extensible method
and event + data field).
• Homogeneous scoreboards should normally be provided as part of eVC but instantiation and
hookup should be left to the user.
• Heterogeneous scoreboards will not normally be provided (except perhaps where a family of
related eVCs are provided by the same vendor).

9-14 e Reuse Methodology


Reference
Visualization: Creating User-Friendly Reports

9.4 Visualization: Creating User-Friendly Reports


The vt_util package does basic visualization for packages, envs, and so on. It can be used as is. It can
also be customized by an eVC developer.

Currently, the vt_util package is included with eRM as a beta feature. For more information, see The
vt_util Package ($SPECMAN_HOME/erm_lib/vt_util/docs/vt_util.pdf).

9.5 Status Coordination and End of Test


This section includes:

• “Introduction to Status Coordination” on page 9-15


• “Objection Mechanism” on page 9-17
• “End-Of-Test Mechanism” on page 9-22

9.5.1 Introduction to Status Coordination


This section describes the status coordination mechanism and its application to end-of-test handling.

This mechanism is incorporated as a beta feature in the evc_util of erm_lib. The golden eVCs
demonstrate its use.

Note The current version of this spec is similar in spirit but different in some details from earlier
versions.

This section includes:

• “General Requirement for Status Coordination” on page 9-15


• “Requirements for End-Of-Test Handling” on page 9-16
• “Overview of Status Coordination Solution” on page 9-16

9.5.1.1 General Requirement for Status Coordination


Coordination tasks like end-of-test, end-of-reset, and end-of-initialization are all similar in nature. In
essence, we need a general way to wait until every unit that cares about a proposed status agrees to that
status, complete with the ability of parent units to control the propagation from their subunits towards
sys (as in the case of end of test).

Other, related requirements for the status coordination mechanism are:

e Reuse Methodology 9-15


Reference
Introduction to Status Coordination

• It must allow waiting until the proposed status is propagated all the way to sys or (if required) until
the status is propagated to some intermediate units.
• The proposed status might be applicable only to some eVCs and not to others.
• Status coordination can be easily debugged.

9.5.1.2 Requirements for End-Of-Test Handling


For a flexible, plug-and-play eVC methodology, eVCs normally must not stop the run unilaterally. On
the other hand, eVCs (and units in general) must be able to:

• Object to stopping the run and later withdraw that objection.


• Decide how to propagate changes in the objection status of its subunits upward toward sys. For
example, a unit might decide that when all its subunits withdraw their objections, it still requires 40
cycles of drain time until it removes its own objection.

When a consensus to stop is propagated all the way to sys, the stop_run() method is called
automatically. The stop_run() method can also be called directly at any time (for example, for
debugging purposes).

9.5.1.3 Overview of Status Coordination Solution


The solution for the general status coordination requirements (see “General Requirement for Status
Coordination” on page 9-15) is the objection mechanism. It is based on the observation that status
coordination can often be described as follows:

• Most units do not care about a proposed status.


• Those units who do care would raise an initial objection to the status and later withdraw that objection.
Following is a summary of the solution. For details, see “Objection Mechanism” on page 9-17.

objection_kind
The predefined enum type objection_kind contains all topics for which the objection mechanism is
needed.

It initially contains the single value TEST_DONE, but it can be extended by the user.

For more information on objection_kind, see “objection_kind enum” on page 9-18

Main Methods of any_unit


any_unit contains the following main methods (each of which gets objection_kind as a parameter):

9-16 e Reuse Methodology


Reference
Objection Mechanism

• raise_objection(kind: objection_kind)
• drop_objection(kind: objection_kind)
A unit calls these methods when it wants to raise or drop an objection to objection_kind.

Note By default, each objection is dropped.

There is also an all_objections_dropped(kind: objection_kind) method. It is called by the system when


the last objection (in the whole tree starting from the unit itself) for the objection_kind is dropped. This
method is initially empty. The user extends it.

For more information on the methods of any_unit, see “Methods of any_unit” on page 9-18.

Debugging Aids
For each of the units, the show objection command shows the current objection counter and objection
total. (For more information on the objection counter and objection total, see “Objection Counter and
Objection Total” on page 9-18.

The trace objection command turns tracing of the objection mechanism on and off. When on, each
objection raised or dropped prints a message.

For more information on debugging aids, see “Debugging Aids” on page 9-21.

End-Of-Test Solution
The end-of-test solution is built on top of the general objection mechanism.

• There is a predefined TEST_DONE objection_kind.


• sys.all_objections_dropped(TEST_DONE) calls stop_run().
For more information on the objection mechanism, see “End-Of-Test Mechanism” on page 9-22.

9.5.2 Objection Mechanism


This section explains the objection mechanism in detail. It includes:

• “objection_kind enum” on page 9-18


• “Objection Counter and Objection Total” on page 9-18
• “Methods of any_unit” on page 9-18
• “Behavior upon quit() and rerun()” on page 9-20

e Reuse Methodology 9-17


Reference
Objection Mechanism

• “Debugging Aids” on page 9-21

9.5.2.1 objection_kind enum


The predefined enum type objection_kind contains all topics for which the objection mechanism is
needed.

Initially, it contains the single value TEST_DONE:


type objection_kind: [TEST_DONE];

You can extend objection_kind to add other kinds. For example, you can add soft reset as follows:
extend objection_kind: [SOFT_RESET_DONE];

9.5.2.2 Objection Counter and Objection Total


For each objection_kind, each unit holds two pieces of information:

• Objection counter: The current number of objections in the unit itself, regardless of its subunits. If
there is no objection, the counter is 0.
• Objection total: The total number of objections in the tree that includes both the unit itself and all of
its subunits.

All of the methods of the API (all of them under any_unit) are tightly related to these two pieces of
information. For details on the methods of any_unit, see “Methods of any_unit” on page 9-18.

9.5.2.3 Methods of any_unit


Table 9-1 describes all of the methods of any_unit (each of which gets objection_kind as a parameter).

Table 9-1 Objection Mechanism Methods

Method Description

raise_objection(kind: objection_kind) By calling this method, the unit increments by 1 its


objection counter to objection_kind.

drop_objection(kind: objection_kind) By calling this method, the unit decrements by 1 its


objection counter to objection_kind.
Calling this method when the objection counter is 0 results
in an error.

9-18 e Reuse Methodology


Reference
Objection Mechanism

Table 9-1 Objection Mechanism Methods (continued)

Method Description

all_objections_dropped(kind: This extensible method is initially empty, except


objection_kind) sys.all_objections_dropped() when the kind is
TEST_DONE (see “End-Of-Test Solution” on page 9-17).
This method is called by Specman whenever the objection
total for objection_kind goes down to zero in the current
unit. In other words, whenever the objection status for
objection_kind is changed in some unit (by calling
raise_objection() or drop_objection() on that unit), the
total for that unit changes immediately. If the total becomes
0, all_objections_dropped() gets called on the unit.
After all_objections_dropped() returns, Specman
continues going up the unit tree towards sys, decrementing
the counter (and hence the total) and calling
all_objections_dropped() for any unit in which the total is
zero.
This method is the main workhorse for doing things upon
the change (for example, raising another objection, starting
a TCM that will drop an objection later, and so on).
Note This is the only objection mechanism method that
should be extended by the user.

get_objection_counter(kind: Returns the objection counter for the unit, that is, the
objection_kind): int current number of objections to objection_kind in the unit
itself, regardless of its subunits.

get_objection_total(kind: Returns the objection total of the unit, that is, the total
objection_kind): int number of objections to objection_kind in the tree that
includes both the unit itself and all of its subunits.

get_objection_list(kind: Returns the list of units directly under the unit (not
objection_kind): list of any_unit including it) for which the objection total is not zero.

e Reuse Methodology 9-19


Reference
Objection Mechanism

Example

Figure 9-3 Objection Status Example

Counter : 1
Unit A
Total : 8

Counter : 5
Unit B
Total : 5

Counter : 0
Unit C
Total : 0

Counter : 0
Unit D
Total : 2

Counter : 1
Unit E
Total : 1

Counter : 0
Unit F
Total : 0

Counter : 1
Unit G
Total : 1

In the example shown in Figure 9-3, calling get_objection_list() on Unit A returns a list consisting of
Unit B and Unit D. This method is useful if your logic depends on knowing which of the immediate
descendents is responsible for rejecting a proposed status such as stopping the run.

Note In this example, for Unit A, get_objection_list() returns a list of two units, whereas
get_objection_total() returns a count of 8.

9.5.2.4 Behavior upon quit() and rerun()


The quit() method of any_unit drops all objections to all objection kinds for the relevant unit. In other
words, when a unit calls the quit() method, the unit’s objection counter is automatically set to 0. This
ensures that a dead (non-active) unit cannot deadlock the objection mechanism.

Notes
• As rerun() calls quit(), it has the same effect as quit() on the objection mechanism. rerun() also
calls run(), restarting all initially started TCMs. Therefore, if the unit called raise_objection() in
some started TCM (or in run()), it will do it again after rerun(). For this reason, we recommend
raising and dropping objections only during run() or later.

9-20 e Reuse Methodology


Reference
Objection Mechanism

• It could happen that there is no objection to end of test during reset because of the effect of the quit()
method mentioned above. This will only happen if all sequences are reset. In that case, to avoid
stopping the simulation, the unit responsible for reset must raise an objection and drop the objection
only after the sequences restart.

9.5.2.5 Debugging Aids


Two commands ease the job of debugging the objection mechanism:

• show objection
Syntax:
show objection [-kind=objection_kind]
This command shows the current objection counter and total for each of the units, for
objection_kind (default: TEST_DONE).
Note If you issue this command while in the middle of the propagation process (for example, after
hitting a breakpoint on some_unit.all_objections_dropped()), you will notice that the counters of
all units between some_unit and sys are not yet decremented. This is consistent with the algorithm
described above.

• trace objection
Syntax:
trace objection [on|off]
This command turns the tracing of the objection mechanism (for all objection kinds) On and Off.
When On, the following things are reported (via the messaging mechanism):
• Raising and dropping objections (at MEDIUM verbosity)
• Calling all_objections_dropped() (at LOW verbosity)
• Stopping the run when sys.all_objections_done(TEST_DONE) is called (at NONE verbosity)

Example 1 Creating Objection Reports from Your e Code


You can make Specman produce an objection report from your e code. The following example produces
a report on DUT error.
extend dut_error_struct {
write() is also {
specman("show objection");
};
};

e Reuse Methodology 9-21


Reference
End-Of-Test Mechanism

Example 2 Customizing Objection Report Format


You can customize the format of your objection reports. To do that, you must create a new method that
creates a report using the unit methods get_objection_counter() and get_objection_total() in the
fashion that you specify. The following example defines the my_obj_report() method for this purpose.
extend sys {
my_obj_report(kind : objection_kind) is {
var obj_units : list of any_unit =
get_all_units(any_unit).all(
.get_objection_total(kind) > 0).reverse();
outf("-----------------------------------------------------\n");
outf("Objection Report:\n");
outf("Counter Total Env e path\n");
outf("------- ----- ---- ------\n");
for each (u) in obj_units {
outf("%-7d %-5d %-7s %-6s\n", u.get_objection_counter(kind),
kind u is an any_env ? u.short_name() : "", u.e_path());
};
};
};

When you want to produce this report, you must call your user-defined method. For example, you could
produce this report on DUT error as follows.
extend dut_error_struct {
write() is also {
sys.my_obj_report(TEST_DONE);
};
};
Note This report cannot be activated from stop_run(). The reason is that stop_run() calls quit(),
which drops all objections (as explained in “Behavior upon quit() and rerun()” on page 9-20).

9.5.3 End-Of-Test Mechanism


The end-of-test mechanism is implemented on top of the general status coordination mechanism. The
rest of this section explains the process.

• “Basic End-Of-Test Mechanism” on page 9-23


• “End-Of-Test Handling Examples” on page 9-23
• “Converting Old Code” on page 9-25

9-22 e Reuse Methodology


Reference
End-Of-Test Mechanism

9.5.3.1 Basic End-Of-Test Mechanism


There is an objection_kind called TEST_DONE.

Also, the following code is already included with the objection logic:
extend sys {
all_objections_dropped(kind: objection_kind) is {
if kind == TEST_DONE then {
start evc_util_check_objection_and_stop_run();
};
};
};

When the last objection is dropped, Specman waits until the end of the Specman tick and then stops the
run.

Notes
• If no objection is ever raised, then the objection mechanism assumes that there is another process for
stopping the test.
• You can always call stop_run() directly and stop the test immediately. This bypasses the whole
objection mechanism.

9.5.3.2 End-Of-Test Handling Examples

Simple End-Of-Test Handling


A unit that wants to be involved in the end-of-test game simply calls:
raise_objection(TEST_DONE);

at the start, and then, at the end:


drop_objection(TEST_DONE);
Note It is okay to raise and drop this objection several times during a test.

End-Of-Test Handling via Sequences


Typically, you want your proactive sequence drivers to influence end of test. To make that happen, you
would extend the MAIN sequence of the relevant proactive sequences with code like the following:
extend MAIN vr_xbus_sequence {
pre_body() @sys.any is first {
driver.raise_objection(TEST_DONE);
};

e Reuse Methodology 9-23


Reference
End-Of-Test Mechanism

post_body() @sys.any is also {


driver.drop_objection(TEST_DONE);
};
};

You might also want to allow for drain time after the MAIN sequence is done. You could add 20 cycles
to the example above as follows:
extend MAIN vr_xbus_sequence {
pre_body() @sys.any is first {
driver.raise_objection(TEST_DONE);
};
post_body() @sys.any is also {
wait [20] * cycle @driver.clock;
driver.drop_objection(TEST_DONE);
};
};

More Complex End-Of-Test Handling


For a unit to do special processing related to the TEST_DONE, extend all_objections_dropped().

For example, to allow for drain time, assume that “bridge_unit” knows it must wait 40 cycles after all its
children are ready to stop. You can achieve this as follows:
extend bridge_unit {

!stopper_started: bool;

all_objections_dropped(kind: objection_kind) is also {


if kind == TEST_DONE and not stopper_started {
raise_objection(TEST_DONE);
start stopper();
stopper_started = TRUE;
};
};

stopper() @clk is {
wait [NUM_OF_DRAIN_CYLCLES];
drop_objection(TEST_DONE);
};
};

9-24 e Reuse Methodology


Reference
Encrypting Packages

9.5.3.3 Converting Old Code


Assume you have a verification environment that normally stops after 1,000 cycles. Suppose you add to
it an eVC that uses the TEST_DONE objection mechanism to stop after 500 cycles when the main active
sequence in that eVC is done.

If you want to disable that early stop, you have several options. Perhaps the simplest is to change the
watchdog method in the verification environment from:
watchdog() @someclock is {
wait [1000];
stop_run();
};

to:
watchdog() @someclock is {
sys.raise_objection(TEST_DONE);
wait [1000];
sys.drop_objection(TEST_DONE);
};

Alternatively, you could simply disable the automatic stopping mechanism in sys:
extend sys {
all_objections_dropped(kind: objection_kind) is first {
if kind == TEST_DONE then {
return;
};
};
};

9.6 Encrypting Packages


The purpose of encryption is to protect IP by restricting access to implementation details. The problem
with encryption is that it tends to introduce hardships for both developers and end users. An encrypted
package is harder to debug, and users who want to extend the package’s capabilities might not have
some required information (for example, names of fields). Our goal is to protect IP rights while
minimizing the burden of integrating, using, and supporting encrypted packages.

This section includes:

• “How Encryption Works” on page 9-26


• “How Much To Encrypt” on page 9-26
• “Adding Extra Debugging Aids to Encrypted Packages” on page 9-27

e Reuse Methodology 9-25


Reference
How Encryption Works

• “Protecting Non-Encrypted Code” on page 9-27


• “Publishing the Interface of Encrypted Files” on page 9-27

9.6.1 How Encryption Works


The Specman encryption utility takes a list of file names and produces encrypted versions of them. A
feature key can be used to protect the code from being loaded and used without a corresponding license
key.

End users cannot read or edit code in an encrypted file, but they can load the file like any non-encrypted
file. If you use the -visible flag of sn_encrypt.sh, you can see the fields in the Data Browser or a
waveform viewer. However, the debugger cannot read encrypted code, and so error messages do not
display the content of the line.

9.6.2 How Much To Encrypt


In theory, an entire eVC could be encrypted. Users could refer to the user guide to know all necessary
field and method names. In practice, however, some code must be kept open to enable debugging and
user support.

Criteria for What to Encrypt


Stability If code is stable, you can encrypt it. (There is less chance that debugging will be
required.)
Completeness If code is self-sufficient, you can encrypt it. (If users do not need to enhance the
code, they do not need to know implementation details.)
Profitability If code is valuable (and debugging and user support are likely to be minimal),
you can encrypt it.

Examples of What to Encrypt


Checks Users never need to enhance checks. Checks are valuable, and a package has
little value without them.
BFMs BFMs are important code, but their implementation is low-level and hence
unlikely to be enhanced by users. Once BFMs are working, they are unlikely to
require debugging.

9-26 e Reuse Methodology


Reference
Adding Extra Debugging Aids to Encrypted Packages

Examples of What Not to Encrypt


Architecture Even though the architecture is documented, most users find it helpful to see the
basic structure—the relations among the main units and structs.
Sequences Users might want to know how sequences are defined to use them in their tests.
Constraints When adding constraints, users might need to see what constraints already exist.
Users also might need to debug generation.

9.6.3 Adding Extra Debugging Aids to Encrypted Packages


Bearing in mind that debugging becomes more complex with encrypted code, developers might want to
add extra debugging aids to encrypted packages. For example, you can have assertions verifying that all
assumptions are valid and message actions providing information on internal variables.

9.6.4 Protecting Non-Encrypted Code


Non-encrypted code that is considered private to the package (that is, end users should not modify it) can
be protected using the encapsulation feature.

9.6.5 Publishing the Interface of Encrypted Files


A header file should accompany each encrypted file to publish its external and internal interface. The
header file must indicate the access permission for each type, struct, method, and so on.

e Reuse Methodology 9-27


Reference
Publishing the Interface of Encrypted Files

9-28 e Reuse Methodology


10 Golden eVCs
To provide examples of recommended e reuse methodology, some special eVCs are provided. These
Golden eVCs are not intended to provide exhaustive coverage of every technique described in this
manual. Instead, they give a few typical examples of how eVCs can be coded.

There are currently four Golden eVCs under development. They are described in the following sections:

• “XBus eVC” on page 10-1


• “XSerial eVC” on page 10-2
• “XSoC eVC” on page 10-2
• “ATM eVC” on page 10-2
The rest of this chapter discusses the trade-off between flexibility and rigidity in an eVC
environment—the pros and cons of each, how developers decide on what is best for their eVC, and how
they configure their eVC accordingly. (See “eVC Environment: Flexibility vs. Rigidity” on page 10-3.)

10.1 XBus eVC


The XBus Golden eVC is an example of how to code a general-purpose eVC for a bus-based protocol.
The chosen bus protocol chosen is deliberately simple so that attention is focused on the eVC
methodology rather than the difficulties in coding complex BFMs, and so on. The protocol has masters,
slaves, and an arbiter. The protocol supports burst transfers, but it is not pipelined.

For more information on the XBus eVC, see the Verisity XBus eVC User Guide (vr_xbus_evc.pdf) in the
erm_lib/vr_xbus/docs directory.

e Reuse Methodology 10-1


Golden eVCs
XSerial eVC

10.2 XSerial eVC


The XSerial Golden eVC is an example of how to code a general-purpose eVC for a point-to-point
protocol. The chosen protocol is deliberately simple so that attention is focused on the eVC
methodology rather than the difficulties in coding complex BFMs, and so on. The protocol is a
synchronous, full-duplex serial protocol with a frame consisting of 8-bit data, 2-bit address, and 2-bit
frame-kind.

For more information on the XSerial eVC, see the Verisity XSerial eVC Overview
(vr_xserial_overview.pdf) in the erm_lib/vr_xserial/docs directory.

10.3 XSoC eVC


The XSoC RTL design consists of two instances of a core that provides XBus to XSerial TX
functionality. The XSoC Golden eVC is an example verification environment for this design. It uses the
XBus and XSerial eVCs.

For more information on the XSoC eVC, see the Verisity XSoC eVC Overview (vr_xsoc_overview.pdf)
in the erm_lib/vr_xsoc/docs directory.

10.4 ATM eVC


The ATM eVC is a higher-layer eVC that is not specific to a particular physical transport protocol. It
therefore does not have a signal interface. Instead, it has a method call interface that allows lower-layer
eVCs to request and return ATM cell data. Normally, the ATM eVC should be used in conjunction with
one or more physical-layer eVCs.

The eVC can perform verification at either the environment level or the system level.

Note The ATM eVC is intended primarily as an example of layering eVCs. The ATM eVC package
has two examples: one layering the ATM eVC over the XBus eVC and the other layering the ATM eVC
over the XSerial eVC.

For more information on the ATM eVC, see the Verisity ATM eVC Overview (vr_atm_overview.pdf) in
the erm_lib/vr_atm/docs directory.

See Also
• “Layering eVCs” on page 4-15

10-2 e Reuse Methodology


Golden eVCs
eVC Environment: Flexibility vs. Rigidity

10.5 eVC Environment: Flexibility vs. Rigidity


Flexibility is measured by two factors:

• Can users constrain all fields or only some of them?


In a fully flexible environment, users can add any constraint on any field. In a rigid environment,
the developer specifies the control fields (the only fields users can constrain).
• Is the generation order predefined?
In a rigid environment, developers specify the generation order. In a flexible environment, no
generation order is enforced.

The relative advantages of flexibility and rigidity are as follows.

Advantages of Flexibility Advantages of Rigidity

It allows all desired scenarios. The environment is easier to support.

Test writers can add any constraints they want. The environment tends to be safer for users.
They do not have to read the documentation to Working in the limited zone defined by the
understand what can be controlled and how. developer, there is less chance that users will
write constraints that break the environment.

One of the primary tasks of an eVC developer is to determine the appropriate level of flexibility in the
environment. After determining the appropriate level of flexibility, the developer must configure the
eVC accordingly.

• “How to Determine Environment Flexibility” on page 10-3


• “Setting Environment Flexibility Using Generation Order” on page 10-4

10.5.1 How to Determine Environment Flexibility


Developers should weigh up the following factors when deciding on the level of environment flexibility
in their eVC.

e Reuse Methodology 10-3


Golden eVCs
Setting Environment Flexibility Using Generation Order

Environment size In small environments, the risk you take when creating a very flexible
environment is minimal. The code is short, and the number of users is
small.

The bigger the environment, the bigger the risk of flexibility. Can you
really anticipate all constraints users might write? If the generation
breaks, will it be easy to debug the environment?

Our recommendations:

• In small environments (for example, block level), allow a high


degree of flexibility.
• In big environments, make the user interface rigid. Decide which
fields test writers can control. As required, also decide the generation
order and enforce it.

eVC purpose If the eVC is for local use, you can take the risk of it breaking from time
to time to get the advantages of a flexible environment.

On the other hand, if the eVC is for commercial use, debugging at


customer sites is much more complicated. You should minimize the
likelihood of users adding constraints that break the environment.

Field role In general, we recommend having stricter rules for architecture units
and looser rules for data items. For example, you might want to let eVC
users control agent units, but not the monitor unit parameters, which
would be propagated from the agent to which it belongs.

Note According to the above recommendations, you might expect the Golden eVCs to be very flexible.
However, they have been built in a more rigid fashion because their purpose is really to demonstrate
commercial eVCs.

10.5.2 Setting Environment Flexibility Using Generation


Order
You can use value() or gen before to define which fields are the input to the constraints and which are
the output.

If users try to constrain fields that are the output of constraints, they will get a contradiction error from
the generator.

For example, in the XSerial eVC (see “XSerial eVC” on page 10-2), clock signals are constrained in the
agent (vr_xserial_agent_u) and propagated to its monitors.

10-4 e Reuse Methodology


Golden eVCs
Setting Environment Flexibility Using Generation Order

keep tx_monitor.sig_clock == value(sig_tx_clock);

Adding constraints to the monitor's sig_clock results in an error message from the generator. Users
would then understand the developer’s intent from the message and the code.

e Reuse Methodology 10-5


Golden eVCs
Setting Environment Flexibility Using Generation Order

10-6 e Reuse Methodology


Index

A 7-6
architecture diagrams, legend for
active agents 4-25 brief 4-5
agents full 4-26
components 4-8 architecture diagrams, legend, definition 4-26
configuration 4-9 architecture, eVC, basic 4-1
data item naming convention 4-25 at_message_verbosity
definition 4-23 recommended methodology 6-48
examples 4-25 ATM eVC 10-2
in depth 4-6 auto_quit() 5-52
internals 4-8
monitor 4-10
overview 4-7
B
sequence drivers 4-9 BFM 4-10
signals 4-9 BFM, definition 4-23
types of 4-25 BFM-monitor guidelines 4-25
all_objections_dropped() 9-19 BFM-monitor relations 4-24
any_env unit 2-23 BFMs 4-5
connecting to package 2-29 body() TCM 5-12
example 2-23
methods, user-visible 2-24 C
any_sequence, interface 5-83
any_sequence_driver, interface 5-85 checker 4-11
any_sequence_item, interface 5-82 checking
any_unit eVC standardization, developer comments
methods 9-18 7-9
methods, main 9-16 clocks 4-6
any_unit.short_name_style() 6-43 clusters, file 3-7
architecture color
eVC standardization, developer comments handling in Specman Elite 6-42

e Reuse Methodology Index-1


Index

message actions, whole cyclic dependencies 3-8


recommended methodology 6-47 alternative approach 3-9
time 6-43
combining eVCs 4-14 D
commands
show doc 8-24 data item, definition 4-23
show packages 2-26 debug output
commands, message 6-23 display, customizing 5-71
detailed explanation 6-25 definitions 4-23
summary 6-23 agent 4-23
compliance checks architecture diagrams, legend 4-26
architecture 7-6 BFM 4-23
checking 7-9 data item 4-23
coverage 7-10 DUT 4-23
documentation 7-13 monitor 4-23
end of test 7-17 package 4-23
general deliverables 7-15 demo.sh file 2-8
messaging 7-12 dependencies
name space 7-2 on package versions, handling 2-15
other possible 7-17 on Specman Elite release, handling 2-15
packaging 7-2 dependencies, cyclic 3-8
reset 7-7 alternative approach 3-9
sequences 7-10 DEPR_MESSAGE_LOGGER 6-4
visualization 7-16 DEPR_SEQUENCE_ITEM_KEYWORD 5-99
constraints, soft DEPR_SEQUENCE_START_KEYWORD 5-97
recommended methodology 6-49 deprecation
coordination, status 9-15 message logger structs 6-4
any_unit methods 9-18 sequence field 5-97
conversion, old code 9-25 sequence item 5-99
debugging 9-17, 9-21 sequence.start() 5-97
introduction 9-15 diagram language 4-4
methods, any_unit 9-18 directories
objection status docs directory 2-8
example 9-20 e directory 2-8
old code, conversion of 9-25 examples directory 2-8
overview 9-16 library directory 2-7
requirements 9-15 other 2-10
solution 9-17 self-verification directory 2-9
coverage 4-11 structure 2-5
default eVC coverage 4-11 directories, eVC
eVC standardization, developer comments source subdirectories 3-2
7-10 do 5-13
current_grabber() 5-77 do item flow, pull mode, using get_next_item()
5-95
Index-2 e Reuse Methodology
Index

do item flow, pull mode, using try_next_item() combining eVCs 4-14


5-96 complex 4-12
do item flow, push mode 5-94 simple 4-2
do subsequence flow 5-93 eVC standardization 7-1
documentation checking 7-9
eVC standardization, developer comments coverage 7-10
7-13 developer comments
drop_objection() 9-18 architecture 7-6
DUT, definition 4-23 documentation 7-13
DUT, example 4-2 end of test 7-17
general deliverables 7-15
E messaging 7-12
monitor 7-13
e directory 2-8 name space 7-2
eDoc 8-21 other possible sections 7-17
eDoc window 8-22 packaging 7-2
output 8-23 reset 7-6
report 8-23 sequences 7-10
report input 8-23 visualization 7-16
using 8-21 reset 7-7
eDoc window 8-22 evc/docs/ 3-3
encryption 9-25 evc/e/ 3-2
end of test 9-15, 9-22 evc/examples/ 3-3
eVC standardization, developer comments evc_util package 2-4
7-17 eVCs 1-3
handling defined 1-3
complex 9-24 plug-and-play 1-5
examples 9-23 reuse requirements 1-5
requirements 9-16 VEs, versus 1-4
via sequences 9-23 eVCs, golden 10-1
simple 9-23 ATM eVC 10-2
introduction 9-15 XBus eVC 10-1
solution 9-17 XSerial eVC 10-2
end-of-test XSoc eVC 10-2
basic 9-23 events 4-6
end-to-end scoreboards 9-13
enumerated logical names 9-7
env, definition 4-23
F
eRM compliance checks 7-1 FAQs, modeling 4-22
eRM release library 1-2 file names, package-relative, using 2-10
erm_lib 1-2 files
eVC architecture, basic 4-1 cyclic dependencies 3-8
eVC architecture, typical 4-1 files, accessing 2-10
eVC example files, eVC
e Reuse Methodology Index-3
Index

clusters 3-7 solution overview 5-60


cyclic dependencies, alternative approach layering eVCs 4-15
3-9 layering, protocols 5-52
importing 3-7 basic layering 5-56
naming guidelines 3-4 data control 5-58
partitioning source into 3-3 different configurations at elaboration time
5-58
G general case 5-59
introduction 5-53
general deliverables many-to-many 5-57
eVC standardization, developer comments many-to-one 5-57
7-15 one-to-many 5-57
get_objection_counter() 9-19 one-to-one 5-57
get_objection_status() 9-19 styles of layering 5-56
golden eVCs 10-1 timing control 5-58
ATM eVC 10-2 library, release, eRM 1-2
XBus eVC 10-1 logger
XSerial eVC 10-2 file
XSoc eVC 10-2 recommended methodology 6-44
grab() 5-74 screen
recommended methodology 6-44
I loggers
IDs 9-6 concerned 6-21
importing files 3-7 constrainable fields 6-38
in_sequence() 5-80 examples 6-39
in_unit() 5-81 fields, constrainable, how used 6-38
instance names 9-6 messages, handling 6-21
XBus Example 9-9 logical names, enumerated 9-7
instance names and IDs 9-6
uses of 9-8 M
instantiating entities 3-5 message action 6-16
is_blocked() 5-76 examples 6-17
is_grabbed() 5-77 message_tag 6-20
is_relevant() 5-51, 5-78 output appearance 6-18
semantics 6-17
L syntax 6-16
language, diagram 4-4 verbosity, recommended usage 6-19
last() 5-78 message loggers 6-20
layer connection process 4-18 struct deprecation 6-4
layering message messages 6-1
late binding 5-64 message output
low-layer sequence 5-62 time, scaling 6-51
message_logger
Index-4 e Reuse Methodology
Index

extending O
recommended methodology 6-51
message_logger methods 6-32 objection 9-17
called while handling messages 6-34 all_objections_dropped() 9-19
configuration, setting 6-33 any_unit methods 9-18
configuration, showing 6-34 counter 9-18
query for message information 6-35 drop_objection() 9-18
message_tag 6-20 get_objection_counter() 9-19
messaging 6-1 get_objection_total() 9-19
colors for message actions 6-42 objection counter 9-18
computing the short_name_path() of a unit objection total 9-18
6-40 objection_kind enum 9-18
eVC standardization, developer comments raise_objection() 9-18
7-12 total 9-18
loggers, configuring via constraints 6-37 objection_kind 9-16, 9-18
methodology, recommended 6-43 objection_kind enum 9-18
procedural interface 6-32
requirements 6-2 P
solution 6-3 package, definition 4-23
messaging commands 6-23 PACKAGE_README.txt file 2-7, 2-19
when to issue examples 2-20
recommended methodology 6-49 headers 2-19
modeling, FAQs 4-22 location 2-19
monitor packages
checking 4-10 checking legality 2-22
coverage 4-10 defining a verification component package
eVC standardization, developer comments 2-1
7-13 as e concept 2-2
global monitor 4-10 evc_util 2-4
monitor, definition 4-23 file names, package-relative, using 2-10
monitor-BFM guidelines 4-25 importing files within same e source
monitor-BFM relations 4-24 directory 2-11
monitors 4-5 kinds of 2-2
naming conventions 2-3
N package directory 2-7
name space package name, choosing 2-3
eVC standardization, developer comments packing
7-2 simple way 2-14
names, logical, enumerated 9-7 readme file 2-7, 2-19
nice_string() 5-71 description 2-19
non-env utilities, instantiating 2-29 examples 2-20
headers 2-19
location 2-19

e Reuse Methodology Index-5


Index

receiving libraries 2-28 rerun() 9-4


shadowing 2-11 rerun(), behavior upon 9-20
shipping libraries 2-28 reset
shipping new versions 2-13 eVC standardization, developer comments
verification component package, definition 7-7
2-1 multiple resets, supporting 9-1
version dependencies 2-15 reset methodology
version number 2-12 revisions 9-2
versions, handling 2-12 timing 9-5
packaging resets, multiple
eVC standardization, developer comments requirements 9-1
7-2
packing version, simple way 2-14 S
passive agents 4-25
protocols, layering 5-52 scalar IDs 9-8
basic layering 5-56 scenarios
data control 5-58 implementing with sequence struct 5-12
different configurations at elaboration time scenarios
5-58 See also sequences
general case 5-59 scoreboard
introduction 5-53 definition 9-12
many-to-many 5-57 scoreboards
many-to-one 5-57 adding 9-12
one-to-many 5-57 end-to-end 9-13
one-to-one 5-57 end-to-end hooks 9-13
styles of layering 5-56 memory access 9-13
timing control 5-58 recommendations 9-14
sequence drivers
common base 5-46, 5-48
Q sequence field deprecation 5-97
quit(), behavior upon 9-20 sequence items
quitting 5-52
R sequence.item deprecation 5-99
sequence.start() deprecation 5-97
raise_objection() 9-18 sequence.start() flow 5-92
reactive agents 4-25 sequences 5-1
readme file, packages 2-7, 2-19 common base 5-46, 5-47
description 2-19 complex scenarios, implementing 5-35
examples 2-20 concurrent sequence kind, defining 5-36
headers 2-19 configurations, before starting 5-37
location 2-19 constraining with unit IDs 5-24
receiving debugging 5-67
packages, libraries 2-28 defining 5-5
release library, eRM 1-2 defining behavior of 5-12
Index-6 e Reuse Methodology
Index

defining using the sequence statement 5-5 sequence-related pseudo-routines 5-80


do action queue, forcing reevaluation 5-51 SIMPLE sequence 5-90
drivers, passing of 5-27 simple sequences 5-90
eVC standardization, developer comments for SoC 5-28
7-10 SoC sequence example 5-30
file organization 5-24 tracing 5-67
flow diagrams 5-91 unit attributes, migrating 5-33
flow of control and data 5-4 using in environment 5-4
generating in advance 5-34 virtual sequences, using 5-25
generation-related aspects, advanced 5-31 virtual, creating 5-26
implementing 5-11 writing tests 5-20
initializations, before starting 5-37 dedicated, creating new sequence kind
interface 5-82 5-23
interrupt sequences 5-37 random, setting weights 5-21
introduction 5-2 simple, by redefining main body() 5-20
limitations, known 5-99 typical, using sequence library 5-21
same item cannot be used in two unit-related, using unit ID 5-23
different sequences 5-99 set message 6-25
sequences supported only from Specman set message -file 6-29
Elite version 4.0 5-100 set message filter 6-26
main 5-90 set message -flush_frequency 6-30
MAIN sequence 5-90 set message -format 6-30
message set message -screen 6-30
recommended methodology 6-48 set message -style 6-30
modifying 5-21 set message -units 6-28
other drivers, making behave 5-28 shadow agents 4-25
parameterizing 5-16 shipping
parameters, propagating in sequence tree packages
5-33 libraries 2-28
quitting 5-52 versions, new 2-13
random 5-90 short names
RANDOM sequence 5-90 handling
read/write interface, DUT-independent 5-41 recommended methodology 6-46
rerunning 5-39 short_name() 6-41
resetting 5-39 short_name_path() 6-40
resources, locking 5-44 how it is computed 6-41
scenarios, advanced 5-35 how it works 6-41
scheduling of items, controlling 5-43 short_name() 6-41
sequence driver, hooking to environment 5-9 show doc
sequence item, defining 5-5 syntax 8-24
sequence kinds, predefined 5-89 show message 6-31
sequence library, creating 5-19 show message -actions 6-32
sequence-related methods 5-72 recommended methodology 6-51

e Reuse Methodology Index-7


Index

show message -logger 6-32 requirements 9-16


show message -units 6-32 via sequences 9-23
show packages command 2-26 simple 9-23
show packages, output example 2-26 introduction 9-15
show sequence 5-70 solution 9-17
signals, DUT 4-6 trace output
sn_which.sh shell script 2-11 display, customizing 5-71
SoC designs, eVCs within 5-29 trace sequence 5-67, 6-48
source subdirectories 3-2 transactions 5-31
start_sequence() 5-72
status coordination 9-15 U
any_unit methods 9-18
conversion, old code 9-25 ungrab() 5-75
debugging 9-17, 9-21 unit IDs, hierarchical 5-24
introduction 9-15 user interface, enhancing 5-17
methods, any_unit 9-18
objection status V
example 9-20 verb tenses
old code, conversion of 9-25 recommended methodology 6-49
overview 9-16 verbosity-num
requirements 9-15 verbosity levels 6-19
solution 9-17 version number, packages 2-12
stop() 5-73 visualization
styles eVC standardization, developer comments
handling 7-16
recommended methodology 6-46 visualization toolkit
subdirectories, source 3-2 reports, user-friendly 9-15
suffixes, adding to types 2-29
syntax
show doc 8-24
W
wave sequence 5-70
T
tags
X
special XBus eVC 4-13, 10-1
recommended methodology 6-48 XSerial eVC 4-2, 10-2
terminology 4-23 XSoC eVC 4-14, 10-2
test en d
handling
complex 9-24
test end 9-15, 9-22
basic 9-23
handling
examples 9-23
Index-8 e Reuse Methodology

You might also like