e Reuse Methodology (eRM) Developer Manual Version 4.3.5
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 1.2 1.3
1.4
2
About This Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-1 About the eRM Release Library (erm_lib) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-2 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 Conventions in This Manual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-6
Verification Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2-1 2.1
2.2
2.3
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 Package-Related Naming Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-3 2.2.1 Choosing a Package Name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-3 2.2.2 evc_util Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-4 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
3.2
iv
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 Partitioning eVC Source into Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-3
e Reuse Methodology
Contents
3.3 3.4 3.5 3.6 3.7
4
File Naming Guidelines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-4 Instantiating Entities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-5 Importing Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-7 File Clusters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-7 Files: Cyclic Dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-8 3.7.1 An Alternative Approach to Cyclic Dependencies . . . . . . . . . . . . . . . . . . . . . 3-9
Typical eVC Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4-1 4.1
4.2
4.3 4.4 4.5
4.6
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 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 A More Complex eVC Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-12 Combining eVCs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-14 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 Modeling FAQs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-22
e Reuse Methodology
v
Contents
4.7
5
Sequences: Constructing Test Scenarios . . . . . . . . . . . . . . . . . . . .5-1 5.1 5.2 5.3
5.4
5.5
5.6 5.7
vi
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
Introduction to Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-2 How to Use Sequences in Your Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-4 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 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 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 Sequence File Organization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-24 Using Virtual Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-25
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.9.9 Handling Pipelined Protocols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-46 5.10 Miscellaneous Advanced Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-49 5.10.1 Disabling Automatic Launch of the MAIN Sequence . . . . . . . . . . . . . . . . . . 5-50 5.10.2 Creating a Common Base for Your Sequences and Sequence Drivers . . . . . 5-50 5.10.2.1 Creating a Common Base for Your Sequences . . . . . . . . . . . . . . . . 5-51 5.10.2.2 Creating a Common Base for Your Sequence Drivers . . . . . . . . . . 5-51 5.10.3 Applying Default Behavior When No Item Is Done . . . . . . . . . . . . . . . . . . . 5-52 5.10.4 Synchronization within a Cycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-53 5.10.4.1 Delaying the Driver Clock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-53 5.10.4.2 Solving Possible Race Conditions . . . . . . . . . . . . . . . . . . . . . . . . . . 5-54 5.10.4.3 Forcing a Reevaluation of the do Action Queue . . . . . . . . . . . . . . . 5-55 5.10.5 Quitting Sequences and Sequences Items . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-55 5.11 Layering of Protocols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-56 5.11.1 Introduction to Layering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-56 5.11.1.1 What Is Layering of Protocols? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-57 5.11.1.2 Layering and Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-58 e Reuse Methodology
vii
Contents
5.11.2
5.12
5.13
5.14
5.15 5.16
5.17
viii
Styles of Layering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-59 5.11.2.1 Basic Layering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-60 5.11.2.2 One-to-One, One-to-Many, Many-to-One, Many-to-Many . . . . . . 5-61 5.11.2.3 Different Configurations at Pre-Run Generation and Runtime . . . . 5-61 5.11.2.4 Timing Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-62 5.11.2.5 Data Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-62 5.11.2.6 Complex Inter-Packet Dependencies . . . . . . . . . . . . . . . . . . . . . . . . 5-62 5.11.2.7 Using Virtual Sequence Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-63 5.11.3 Using Layered Sequence Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-64 5.11.3.1 Overview of the Layering Solution . . . . . . . . . . . . . . . . . . . . . . . . . 5-64 5.11.3.2 Introducing Layering into the Low-Layer Sequence . . . . . . . . . . . . 5-66 5.11.3.3 Late Binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-68 Tracing and Debugging Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-71 5.12.1 trace sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-71 5.12.1.1 trace sequence Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-73 5.12.2 wave sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-74 5.12.3 show sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-74 5.12.4 Customizing Display of Trace and Debug Output . . . . . . . . . . . . . . . . . . . . . 5-75 Sequence-Related Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-76 5.13.1 start_sequence() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-76 5.13.2 stop() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-77 5.13.3 grab() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-78 5.13.4 ungrab() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-79 5.13.5 is_blocked() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-80 5.13.6 is_grabbed() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-81 5.13.7 current_grabber() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-81 5.13.8 is_relevant() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-82 5.13.9 last() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-82 Sequence-Related Pseudo-Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-84 5.14.1 in_sequence() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-84 5.14.2 in_unit() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-85 Sequence Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-86 Predefined Sequence Kinds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-93 5.16.1 MAIN Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-94 5.16.2 RANDOM Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-94 5.16.3 SIMPLE Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-94 BFM-Driver-Sequence Flow Diagrams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-95
e Reuse Methodology
Contents
5.17.1 sequence.start_sequence() Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-96 5.17.2 do Subsequence Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-97 5.17.3 do Item Flow in Push Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-98 5.17.4 do Item Flow in Pull Mode Using get_next_item() . . . . . . . . . . . . . . . . . . . . 5-99 5.17.5 do Item Flow in Pull Mode Using try_next_item() . . . . . . . . . . . . . . . . . . . 5-100 5.18 Sequence Deprecation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-100 5.18.1 Method sequence.start() Deprecation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-101 5.18.2 Field sequence Deprecation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-101 5.18.3 Sequence item Deprecation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-103 5.19 Known Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-103 5.19.1 Same Item Cannot Be Used in Two Different Sequences . . . . . . . . . . . . . . 5-103 5.19.2 Item Children Cannot Be Created with Like Inheritance before Sequence Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-104 5.19.3 Sequences Are Supported Only from Version 4.1 . . . . . . . . . . . . . . . . . . . . 5-104
6
Messaging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6-1 6.1
6.2
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 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
e Reuse Methodology
ix
Contents
6.3
6.4
6.5
6.6
6.7
6.8
6.9
x
The Message Action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-16 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 Message Loggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-20 6.4.1 How Loggers Handle Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-21 6.4.2 Configuring Message Loggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-23 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-26 6.5.2.2 show message Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-31 Messaging Procedural Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-33 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 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 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 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
e Reuse Methodology
Contents
6.9.3 Coloring Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-43 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.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 7.10 7.11 7.12 7.13
8
Packaging and Name Space Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-2 Architecture Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-6 Reset Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-7 Checking Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-9 Coverage Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-10 Sequences Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-10 Messaging Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-12 Monitor Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-13 Documentation Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-13 General Deliverables Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-15 Visualization Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-16 End of Test Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-17 Other Possible Compliance Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-17
The eRM Utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8-1 8.1
Browsing eRM Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-3 8.1.1 The eRM Package Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-5
e Reuse Methodology
xi
Contents
8.2
8.3
8.4
9
Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9-1 9.1
9.2
9.3
xii
Examining Envs and Units . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-5 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 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 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
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 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 Adding Scoreboards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-12 9.3.1 What Is a Scoreboard? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-12
e Reuse Methodology
Contents
9.4
9.5
10
9.3.2 Memory Access Scoreboards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-13 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 Status Coordination and End of Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-15 9.4.1 Introduction to Status Coordination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-15 9.4.1.1 General Requirement for Status Coordination . . . . . . . . . . . . . . . . . 9-15 9.4.1.2 Requirements for End-Of-Test Handling . . . . . . . . . . . . . . . . . . . . 9-16 9.4.1.3 Overview of Status Coordination Solution . . . . . . . . . . . . . . . . . . . 9-16 9.4.2 Objection Mechanism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-17 9.4.2.1 objection_kind enum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-17 9.4.2.2 Objection Counter and Objection Total . . . . . . . . . . . . . . . . . . . . . . 9-18 9.4.2.3 Methods of any_unit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-18 9.4.2.4 Behavior upon quit() and rerun() . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-20 9.4.2.5 Debugging Aids . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-21 9.4.3 End-Of-Test Mechanism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-22 9.4.3.1 Basic End-Of-Test Mechanism . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-23 9.4.3.2 End-Of-Test Handling Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-23 9.4.3.3 Converting Old Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-25 Encrypting Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-25 9.5.1 How Encryption Works . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-26 9.5.2 How Much To Encrypt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-26 9.5.3 Adding Extra Debugging Aids to Encrypted Packages . . . . . . . . . . . . . . . . . 9-27 9.5.4 Protecting Non-Encrypted Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-27 9.5.5 Publishing the Interface of Encrypted Files . . . . . . . . . . . . . . . . . . . . . . . . . . 9-27
Golden eVCs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10-1 10.1 10.2 10.3 10.4 10.5
XBus eVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-1 XSerial eVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2 XSoC eVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2 ATM eVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2 eVC Environment: Flexibility vs. Rigidity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2 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 Scenarios”
How to use Specman sequences in a uniform and efficient way
Chapter 6 “Messaging”
How to create standard messages
Chapter 7 “eVC Standardization Using eRM Compliance Checks”
How to maintain a high standard and uniformity 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:
1-2
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 (in the erm_docs directory)
This directory contains all of the main eRM documentation. It also contains eRM presentations in PDF format.
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).
e Reuse Methodology
Introduction About eVCs
Example directories
These are minipackages that demonstrate use of some specific features 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 packages
These packages offer useful functionality. They are, however, often provided 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 (in the templates directory)
This directory contains templates for eVC user guides (in FrameMaker and MS Word formats) and for eVC training classes (in PowerPoint format).
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
• • • •
Common look and feel, similar activation, similar documentation
• • • • • • • • • • • •
Common way to install eVCs Common way to patch eVCs 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 (control, checking, layering, and so on)
• • • • • • •
Common way to configure eVCs Common way to write tests 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
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
verification environment Commonality in implementation
1.4
• Common data structures • Common eVC testing methodology • Common way to use ports and packages
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 SpeXsim prompt (VHDL, Verilog or mixed-HDL designs). Also denotes a third-party Verilog simulator prompt.
>
Denotes a third-party VHDL simulator prompt.
%
Denotes the UNIX prompt.
1-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. Each reusable verification component should be packaged in its own directory, which: e Reuse Methodology
2-1
Verification Packages Packages as e Concept
• 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
[email protected] 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
co_atm/ PACKAGE_README.txt demo.sh e/ docs/ examples/ verilog/
...
vr_ahb/
shr_visualizer/
PACKAGE_READM E.txt demo.sh e/ docs/ examples/ misc/
PACKAGE_READM E.txt demo.sh e/ docs/ examples/
/cad/evc_lib/ LIBRARY_README.txt evc_util/ PACKAGE_READM E.txt demo.sh e/ docs/ 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/ • docs/ e Reuse Methodology
2-5
Verification Packages Directory Structure
• 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 • “Package Directory” on page 2-7
2-6
e Reuse Methodology
Verification Packages Library Directory
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. For a detailed description of this file, see “PACKAGE_README.txt File” on page 2-19.
e Reuse Methodology
2-7
Verification Packages Package Directory
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. If an example consists of more than one file, it may make sense to create subdirectories for each example.
2-8
e Reuse Methodology
Verification Packages Package Directory
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; import yy; import checks/cell_check;
// xx.e is in same directory as importing file // yy.e is in same directory as importing file // cell_check.e is in e/checks/
Note 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 .. .. 4.7
//All versions from 3.0 onwards //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 Severity
Condition
Notification
Package x is not available in the SPECMAN_PATH
PACKAGE_NOT_FOUND: Package x cannot be found
Warning
The version number of package x is not within the required range of package z
PACKAGE_VER_INCOMP: Package x version y is incompatible with package z
Warning
Package z specifies an open version range for package x, and package x is in that open range but not on the edge
PACKAGE_VER_POSSIBLE_INCOMP: Package x version y might be incompatible with package z
Ignore
Package x requires another Specman version
SPECMAN_VER_INCOMP: Package x is incompatible with Specman version y
Warning
Package x specifies an open version range for Specman , and Specman is in that open range but not on the edge
SPECMAN_VER_POSSIBLE_INCOMP: Package x might be incompatible with Specman version y
Ignore
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
2-18
version
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.
2-20
e Reuse Methodology
Verification Packages PACKAGE_README.txt Headers
PACKAGE_README.txt for an eVC ---------- 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:
[email protected] -- 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: e Reuse Methodology
2-21
Verification Packages Checking Package Legality
....1. ....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:
[email protected] (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:
2-22
e Reuse Methodology
Verification Packages any_env Unit
/any_lib/any_package/e/any_package_top.e
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:
[email protected]
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:
[email protected] 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:
[email protected] 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:
[email protected] 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:
[email protected] 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, feature last)
evc_master.e, evc_checker.e 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
• Imports all files • Instantiates eVC entities • Passed to sn_compile
evc_top.e
Table 3-3
Files Owned by Users (supplied in evc/examples directory)
File Name evc_config_template.e (evc_config_*.e)
Description
• • • • •
Shows all eVC config fields 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 (evc_defines_*.e)
3.4 ’
Table 3-4
Environment constants that use define (if needed)
Instantiating Entities 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; import ./sub_dir/evc_another_file.e;
// File in same directory // 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 evc/e/evc_env.e;
// Import the top level file of the eVC // 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;
3.6
// Import the evc_util utility
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 Serial Logic
Bus 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 Config:
...
RX Agent
TX Agent
Config
Config
Signal Map
Signal Map
Sequence Driver
Sequence Driver
seq
Mon
seq
BFM
Mon
BFM
DUT Bus Logic
4-2
Serial Logic
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 Config: ...
TX_AND_RX Agent Config Signal Map Sequence Driver seq RX Mon
TX Mon
TX 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
Unit
unit
Struct
struct
Data item
Unit instantiation
Subtype Struct/unit pointer
Enclosing unit Instantiated unit Enclosing unit Subtype struct
Field grouping
Topic: field 1 ...
DUT access DUT
unit
Most important, 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 Figure 4-5
Components of Agents Agent Internals Agent
Config: active_passive name kind == TX
ACTIVE
Signal Map
Sequence Driver
Passive
seq
Mon has_coverage has_checker
BFM
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 xserial_env
xbus_env Config : name has_... ...
MASTER Agent
SLAVE Agent
DUT
Config: name
... Config
Config
Config
SD
SD
SD
M
B
M
B
RX Agent
TX Agent
Config
Config
Signal Map
Signal Map
SD
SD
M
B
seq
seq
seq
seq
seq
M
ARBITER Agent
M
B
M
xbus
B
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 xbus_env Config: name has_...
...
MASTER Agent
SLAVE Agent
ARBITER Agent
Config
Config
Config
Signal Map
SD
SD
seq
M
DUT
M
B
Signal Map
M
SD seq
seq
seq
B
Signal Map
Sequence driverSD
SD
seq
M
xserial_env xserial_env TX Agent RX Agent Config: RX Agent TX Agent nameConfig: Config ... name Config Config Config ... Signal Signal
M
B
xbus
B
M
B
xbus xbus
serial dev #2
serial 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 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
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); }; }; }; };
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. 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
e Reuse Methodology
4-19
Typical eVC Architecture Inter-Layer Connection
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 RX Agent
TX Agent
xserial_env xserial_env RX TX Agent RX Agent
or
TX 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 X Agent
or
x_env
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
e Reuse Methodology
An independent and modular eVC, utility, or shareware.
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 Monitor
Sub-Entities 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.
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-24
e Reuse Methodology
Typical eVC Architecture Agent Types
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
AHB
eVC master
eVC slave
USB
host
device
XSerial
TX (RX)
PASSIVE
(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 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.
e Reuse Methodology
4-25
Typical eVC Architecture Full Legend for Architecture Diagrams
4.7.5
Full Legend for Architecture Diagrams
Figure 4-8
Full Legend for Architecture Diagrams
Struct
struct
Data flow
Data item DUT access Unit
DUT
unit
Unit instantiation
Subtype Struct/unit pointer
Field grouping
Sequence Driver
Enclosing unit
Color
Instantiated unit
Monitor BFM DUT
Enclosing unit Subtype struct Topic: field 1 field 2
Sequence execution— unit
Sequential:
seq
seq seq
Parallel:
seq
seq 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-49 • “Layering of Protocols” on page 5-56 • “Tracing and Debugging Sequences” on page 5-71
Reference
• “Sequence-Related Methods” on page 5-76 • “Sequence-Related Pseudo-Routines” on page 5-84 • “Sequence Interface” on page 5-86 • “Predefined Sequence Kinds” on page 5-93 • “BFM-Driver-Sequence Flow Diagrams” on page 5-95 • “Sequence Deprecation” on page 5-100 • “Known Limitations” on page 5-103
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:
5-2
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.
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: Sequence Item
Config: ...
id kind == TX 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.
Note Throughout these sections, the examples used are from the eRM library.
See Also • 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
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 = base_sequence_name
The name of the sequence struct your sequence inherits from (default: any_sequence). For more information, see “Creating a Common Base for Your Sequences and Sequence Drivers” on page 5-50.
sequence_driver_type = base_sequence_driver_name
The name of the sequence driver unit your sequence driver inherits from (default: any_sequence_driver). For more information, see “Creating a Common Base for Your Sequences and Sequence Drivers” on page 5-50.
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. For more information about virtual sequences, see “Creating a Virtual Sequence” on page 5-26. 5-6
e Reuse Methodology
Sequences: Constructing Test Scenarios Defining the Sequence and Its Driver Using the sequence Statement
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-51. For the full list of the sequence struct members, see “any_sequence Interface” on page 5-88.
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-51.
• For the full list of the sequence driver unit members, see “any_sequence_driver Interface” on page 5-89.
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
See Also • For the full list of the item struct members, see “any_sequence_item Interface” on page 5-87
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 { ... }; };
See Also • “Predefined Sequence Kinds” on page 5-93
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 { ... };
e Reuse Methodology
5-9
Sequences: Constructing Test Scenarios Hooking the Sequence Driver to the Environment
Have a BFM that knows how to drive a cell into the DUT: unit ex_atm_bfm { 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-94.
• 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
e Reuse Methodology
5-11
Sequences: Constructing Test Scenarios Implementing a Scenario Using the Sequence Struct
• “Creating a Sequence Library” on page 5-19
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:
• Use the do action. For example: do sequence;
To start the body() TCM:
• Use the any_sequence predefined method start_sequence(). For example: 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.
5-12
e Reuse Methodology
Sequences: Constructing Test Scenarios Implementing a Scenario Using the Sequence Struct
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. 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-76.
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-97. 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-99 and Figure 5-11 on page 5-98.
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-78 and “is_relevant()” on page 5-82.)
• 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
[ ]" as { do cell keeping { .len == ; .kind == ; .x == ; }; };
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 hook file
Extends the sequence for use with a specific DUT and hooks 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.
See Also • 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-89. The following sections describe how this is done. e Reuse Methodology
5-25
Sequences: Constructing Test Scenarios Creating a Virtual Sequence
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. 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;
2.
// Note no "item=" option
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() { .... };
5-26
e Reuse Methodology
Sequences: Constructing Test Scenarios Passing of Sequence Drivers
4.
Define the sequence driver in the appropriate unit in your environment (probably the lowest unit enclosing all of the component 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-86.
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 Mon BFM
Memory Controller
DMA Controller CPU Bus System Chip
Bridge Peripheral Bus
UART
GPIO
SD Mon BFM
SD Mon BFM
USB
Ethernet
SD Mon BFM
SD 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 do eth_config keeping { .driver=eth_driver; }; do atm_sequence keeping { .driver=atm_driver; };
atm_env
eth_config seq
atm_sequence
eth_env
ATM Sequence Driver
Ethernet Sequence Driver seq
seq
BFM
5-30
Virtual Driver
seq
seq seq
BFM
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() // // do
@driver.clock is { seq will be generated to LONG GREEN my_sequence (not GREEN LONG order does matter). 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 { it.green_level == 12; 5-32
e Reuse Methodology
Sequences: Constructing Test Scenarios Propagating Parameters in the Sequence Tree
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; };
5.8.3
// Constrain sequence root in driver
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 • “Handling Pipelined Protocols” on page 5-46
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 items
You cannot use last() to retrieve items that were done before the rerun. For more information on last(), see “last()” on page 5-83.
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-55.)
• 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 { 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; }; };
extend ex_atm_driver { // Set interaction mode keep bfm_interaction_mode == PUSH_MODE; // Transfer the item from the // driver to the BFM: // Add a call to the BFM's TCM in // the sequence driver's // send_to_bfm() send_to_bfm(seq_item: ex_atm_cell) @clock is only { bfm.drive_cell(seq_item); }; };
run() is also { 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 Handling Pipelined Protocols
}; };
• 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-98 to Figure 5-12 on page 5-99.
5.9.9
Handling Pipelined Protocols
In pipelined protocols, data items undergo a number of processing phases. For example, a data transfer might be either in the address phase or in the data phase. In addition, the DUT can handle concurrently multiple data items with each item in a different phase. When implementing pipelined scenarios with sequences some typical problems arise:
• How to launch a new data item while the current data item is still being processed • How to ensure that the fields of the data item are stable before sampling them To implement pipelined scenarios: 1.
In the appropriate sequence, list the desired series of pipelined do actions.
2.
Emit the item_done event when a trigger event in the BFM indicates that a new data item should be sent to the DUT. This releases the current do action and lets the sequence perform the next do action.
For example: extend my_sequence { !trans1 : READ transfer; !trans2 : WRITE transfer; body()@driver.clock is { -- List a series of pipelined do actions do trans1; do trans2; }; }; extend my_bfm { bfm_loop()@clock is { while TRUE { trans = driver.get_next_item(); start put_on_bus(trans); 5-46
e Reuse Methodology
Sequences: Constructing Test Scenarios Handling Pipelined Protocols
-- Emit the item_done event when the trigger event occurs wait @need_new_item; emit driver.item_done; }; }; };
If sampling of data items is required, you need a mechanism for detecting when the data-item fields are updated and ready for sampling. In the above example, the sequence can start to do the WRITE burst before the fields of the READ burst are fully updated. To ensure that data-item fields are ready for sampling: 1.
Add a Boolean field to the data item that is set to TRUE when all fields are up to date.
2.
Delay sampling of fields with a wait or sync action that is satisfied when the field is TRUE.
For example: extend transfer { -- Add Boolean field !finished : bool; }; extend my_sequence { !trans1 : READ transfer; body()@driver.clock is { do trans1; -- Delay sampling sync true(trans1.finished); sample(trans1); }; };
When sampling of a pipelined data item’s fields is required immediately after the item is completely processed, then the above approach must be refined. The sampling of each item must occur in a thread distinct from that of the do of the next item. You can achieve this in several ways.
Example 1
Combine do action with associated sampling
extend transfer { -- Add Boolean field !finished : bool; get_data()@driver.clock is { -- Delay sampling e Reuse Methodology
5-47
Sequences: Constructing Test Scenarios Handling Pipelined Protocols
wait true(finished); do_something_with(data); }; }; extend my_sequence { !trans1 : READ transfer; !trans2 : WRITE transfer; body()@driver.clock is { var num_of_items : uint; all of { -- Create separate thread for each do-sample pair { // First thread do trans1; num_of_items = 1; trans1.get_data(); }; {
// Second thread sync true(num_of_items==1); do trans2; trans2.get_data();
}; }; }; extend my_bfm { bfm_loop()@clock is { while TRUE { trans = driver.get_next_item(); start put_on_bus(trans); -- Emit the item_done event when the trigger event occurs wait @need_new_item; emit driver.item_done; }; }; };
Example 2
All do actions in a single thread but sampling in separate threads
extend transfer { -- Add Boolean field !finished : bool; get_data()@driver.clock is {
5-48
e Reuse Methodology
Sequences: Constructing Test Scenarios Miscellaneous Advanced Features
-- Delay sampling wait true(finished); do_something_with(data); }; }; extend my_sequence { !trans1 : READ transfer; !trans2 : WRITE transfer; body()@driver.clock is { message(NONE,"running ",kind," burst"); do trans1; start trans1.get_data(); // Sample in separate thread do trans2; start trans2.get_data(); // Sample in separate thread }; }; extend my_bfm { bfm_loop()@clock is { while TRUE { trans = driver.get_next_item(); start put_on_bus(trans); -- Emit the item_done event when the trigger event occurs wait @need_new_item; emit driver.item_done; }; }; };
5.10 Miscellaneous Advanced Features This section includes:
• “Disabling Automatic Launch of the MAIN Sequence” on page 5-50 • “Creating a Common Base for Your Sequences and Sequence Drivers” on page 5-50 • “Applying Default Behavior When No Item Is Done” on page 5-52 • “Synchronization within a Cycle” on page 5-53 • “Quitting Sequences and Sequences Items” on page 5-55
e Reuse Methodology
5-49
Sequences: Constructing Test Scenarios Disabling Automatic Launch of the MAIN Sequence
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; 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-51 • “Creating a Common Base for Your Sequence Drivers” on page 5-51
5-50
e Reuse Methodology
Sequences: Constructing Test Scenarios Creating a Common Base for Your Sequences and Sequence Drivers
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.
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.
e Reuse Methodology
5-51
Sequences: Constructing Test Scenarios Applying Default Behavior When No Item Is Done
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. 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-54). 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();
5-52
e Reuse Methodology
Sequences: Constructing Test Scenarios Synchronization within a Cycle
if seq_item == NULL { seq_item = new; }; drive_cell(seq_item); emit driver.item_done; }; }; };
See Also • Figure 5-13 on page 5-100 • Figure 5-12 on page 5-99
5.10.4
Synchronization within a Cycle
This section contains:
• “Delaying the Driver Clock” on page 5-53 • “Solving Possible Race Conditions” on page 5-54 • “Forcing a Reevaluation of the do Action Queue” on page 5-55
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:
e Reuse Methodology
5-53
Sequences: Constructing Test Scenarios Synchronization within a Cycle
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. 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:
5-54
e Reuse Methodology
Sequences: Constructing Test Scenarios Quitting Sequences and Sequences Items
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.
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. e Reuse Methodology
5-55
Sequences: Constructing Test Scenarios Layering of Protocols
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-56 • “Styles of Layering” on page 5-59 • “Using Layered Sequence Drivers” on page 5-64
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:
5-56
e Reuse Methodology
Sequences: Constructing Test Scenarios Introduction to 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-57 • “Layering and Sequences” on page 5-58
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;
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.
e Reuse Methodology
5-57
Sequences: Constructing Test Scenarios Introduction to Layering
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 { .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.
5-58
e Reuse Methodology
Sequences: Constructing Test Scenarios Styles of Layering
Layering of Several Sequence Drivers Figure 5-4
Layering Architecture DUT Packet BFM
seq
Packet SD
Multi-Layer Architecture
seq
Frame SD
seq
This packet sequence pulls information directly from the Frame sequence driver
seq
seq seq
DUT Packet BFM Single-Layer Architecture
seq
Packet SD
seq seq
The more general approach uses multiple sequence drivers (see Figure 5-4 on page 5-59). 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.
See Also • “Using Layered Sequence Drivers” on page 5-64
5.11.2
Styles of Layering
This section includes:
e Reuse Methodology
5-59
Sequences: Constructing Test Scenarios Styles of Layering
• “Basic Layering” on page 5-60 • “One-to-One, One-to-Many, Many-to-One, Many-to-Many” on page 5-61 • “Different Configurations at Pre-Run Generation and Runtime” on page 5-62 • “Timing Control” on page 5-62 • “Data Control” on page 5-62 • “Complex Inter-Packet Dependencies” on page 5-63 • “Using Virtual Sequence Drivers” on page 5-63
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-61). 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-60
e Reuse Methodology
Sequences: Constructing Test Scenarios Styles of Layering
Figure 5-5
Layering of Protocols Kinds: RAW LAYER2A LAYER2B Layer 1a
header kind kind Payload (32 Payload heade bytes)(32 bytes)
Layer 1b
header
Layer 2a
address
Layer 2b
address
length
1 byte
1 byte
kind
CRC CRC
Payload (64 bytes)
CRC
Payload (31 bytes)
1 byte Payload (1..100 bytes)
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 kind Payload Payload (32 bytes) hea kind (32 bytes)
CRC CRC
header kind
Payload (32 bytes)
CRC
The conversion mechanism might need to cope with any of the following situations:
e Reuse Methodology
5-61
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-62
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-64, 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-63
Sequences: Constructing Test Scenarios Using Layered Sequence Drivers
Figure 5-7
Most General Case—Using Virtual Sequence Drivers Layering with virtual sequences Layering with connector sequences
L2B SD seq L2A SD
seq
seq
seq
seq
seq
seq
L2A SD
L2B BFM
L1A
seq
seq
seq
seq
Virtual SD
seq
seq
L1B SD seq
L1A BFM
L2A SD
seq
seq
seq
seq seq
seq seq
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-59.) This section includes:
• “Overview of the Layering Solution” on page 5-64 • “Introducing Layering into the Low-Layer Sequence” on page 5-66 • “Late Binding” on page 5-68
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-64
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-58. 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-65
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-66.)
• You can call some intermediate connector method in the lower-layer sequence driver, which will later be extended (see “Late Binding” on page 5-68). For example: raw_data = driver.get_payload();
Figure 5-8
Pulling Information from a High-Level BFM Frame SD seq
seq seq
Frame BFM Packet SD seq
To achieve complex data transformation, we need a BFM or a third-party transformer unit.
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-66
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-64. 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) @sys.any 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-67
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-63). 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-68
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-69
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-70
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-71
For runtime tracing of the creation of sequences and items
wave sequence on page 5-74
For runtime tracing of the items sent by the sequence driver in the waveform viewer
show sequence on page 5-74
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-75.
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 used1 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-71
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(): list of any_sequence_item
• get_item_trace_list(): list of any_sequence_item
• get_sequence_trace_list(): list of any_sequence
Returns a list of all sequences and items handled by the sequence driver Returns a list of only the items handled (sent) by the sequence driver Returns a list of only the sequences handled by the sequence driver
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-72
e Reuse Methodology
Sequences: Constructing Test Scenarios trace sequence
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}; -- (Optional) Prevent trace sequence messages from printing to screen run() is also { specman_command("set message -logger=sys.logger -remove -tags={TRACE_SEQUENCE}");
e Reuse Methodology
5-73
Sequences: Constructing Test Scenarios wave sequence
}; };
See Also • 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-74
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-75
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-76 • stop() on page 5-77 • grab() on page 5-78 • ungrab() on page 5-80 • is_blocked() on page 5-80 • is_grabbed() on page 5-81 • current_grabber() on page 5-82 • is_relevant() on page 5-82 • last() on page 5-83
5.13.1
start_sequence()
Purpose This method of any_sequence is used to initiate the run of a sequence.
5-76
e Reuse Methodology
Sequences: Constructing Test Scenarios stop()
Syntax [sequence-exp.]start_sequence()
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-96
5.13.2
stop()
Purpose This method of any_sequence is used to terminate the run of a sequence.
Syntax [sequence-exp.]stop()
Parameters None
e Reuse Methodology
5-77
Sequences: Constructing Test Scenarios grab()
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.
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()
Purpose This method of any_sequence lets sequences have an exclusive control over a sequence driver.
Syntax [sequence-exp.]grab(driver) @sys.any
Parameters driver
5-78
A BFM sequence driver expression
e Reuse Methodology
Sequences: Constructing Test Scenarios grab()
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).
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-80
e Reuse Methodology
5-79
Sequences: Constructing Test Scenarios ungrab()
5.13.4
ungrab()
Purpose This method of any_sequence stops sequences from having an exclusive control over a sequence driver.
Syntax [sequence-exp.]ungrab(driver)
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-78
5.13.5
is_blocked()
Purpose 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.
5-80
e Reuse Methodology
Sequences: Constructing Test Scenarios is_grabbed()
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.
See Also • grab() on page 5-78
5.13.6
is_grabbed()
Purpose 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-78
e Reuse Methodology
5-81
Sequences: Constructing Test Scenarios current_grabber()
5.13.7
current_grabber()
Purpose 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
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-78
5.13.8
is_relevant()
Purpose 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
5-82
e Reuse Methodology
Sequences: Constructing Test Scenarios last()
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()
Purpose 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
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.
e Reuse Methodology
5-83
Sequences: Constructing Test Scenarios Sequence-Related Pseudo-Routines
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 };
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-85 • in_unit() on page 5-86
5-84
e Reuse Methodology
Sequences: Constructing Test Scenarios in_sequence()
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. 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 };
e Reuse Methodology
5-85
Sequences: Constructing Test Scenarios in_unit()
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.
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:
5-86
e Reuse Methodology
Sequences: Constructing Test Scenarios Sequence Interface
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.
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-71). 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.
e Reuse Methodology
5-87
Sequences: Constructing Test Scenarios Sequence Interface
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(): driver_name
Return the driver for a sequence.
!parent_sequence: any_sequence;
Backpointer to the sequence in which this sequence was created. Assigned 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: any_sequence_driver) @sys.any is undefined
Grab the sequence driver for exclusive access and returns when you have exclusive access.
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.
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-96.
stop()
Terminates my body(), if it exists.
ungrab(driver: any_sequence_driver) is undefined
Releases the grab on a sequence driver and returns immediately.
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 empty
A short string representing the sequence for tracing. It is used by trace sequence, wave sequence, and show sequence (see “Tracing and Debugging Sequences” on page 5-71). The default implementation returns the kind followed by the instance name (for example, “RED atm_sequence-@2”).
5-88
e Reuse Methodology
Sequences: Constructing Test Scenarios Sequence Interface
Table 5-3
any_sequence Interface (continued)
Struct Member
Description
@ended
Emitted immediately after body() is finished.
@started
Emitted just before body() is called.
body() @driver.clock is empty
Main method called by do of parent sequence after it generates the current sequence.
kind: kind_name
The kind field that determines which sequence it is (within its when family).
mid_do(s: any_sequence_item) is empty;
Hook method called in the middle of do, just after s is generated and before it is executed by calling its body() TCM.
post_body() @sys.any is empty;
Hook method called after body() when sequence is started using the start_sequence() method.
post_do(s: any_sequence_item) is empty;
Hook method called at end of do, just after the execution of s.body().
post_trace()
Gets called for every sequence just after a trace message about it gets printed. (Useful for breakpoints.)
pre_body() @sys.any is empty;
Hook method called before body() when sequence is started using the start_sequence() method.
pre_do(is_item: bool) @sys.any is empty;
Hook TCM called at start of a do performed by the sequence. ‘is_item’ 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-87. Table 5-4
any_sequence_driver Interface
Struct Member
Description
BFM Only
Read Only Member (can only be accessed)
current_grabber(): any_sequence
e Reuse Methodology
Indicates which sequence (if any) has exclusive control over a sequence driver.
Yes
5-89
Sequences: Constructing Test Scenarios Sequence Interface
Table 5-4
any_sequence_driver Interface (continued) BFM Only
Struct Member
Description
get_current_item(): any_sequence_item
Returns the item currently being sent. (NULL if the BFM is currently idle.)
Yes
get_index(): int
Returns index of this sequence driver in the all-driver list.
No
get_item_trace_list(): list of any_sequence_item
Returns a list of the items handled (sent) by the sequence driver (the item sublist of the trace log).
Yes
Note The list is populated only if the trace sequence command was activated in On or Log Only mode. get_next_item(): item_name @clock
This TCM should be called in PULL_MODE to receive the next item from the BFM driver. This TCM is blocked until there is an item to do in the driver.
Yes
See also Figure 5-12 on page 5-99. get_num_items_sent(): int
Returns count of items sent (excluding current_item, if any).
Yes
get_sequence_trace_list(): list of any_sequence
Returns a list of the sequences handled by the sequence driver (the sequence sublist of the trace log).
Yes
Note The list is populated only if the trace sequence command was activated in On or Log Only mode. get_trace_list(): list of any_sequence_item
Returns a list of all sequences and items handled by the sequence driver (the full trace log).
Yes
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 sequence driver.
Yes
5-90
e Reuse Methodology
Sequences: Constructing Test Scenarios Sequence Interface
Table 5-4
any_sequence_driver Interface (continued)
Struct Member
Description
try_next_item(): item_name @clock
This TCM should be called in PULL_MODE when 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.
BFM Only Yes
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-100. Read/Write Member (can also be set, constrained, or implemented)
bfm_interaction_mode: bfm_interaction_mode_t
Specifies the way the driver and the BFM interact with each other. Possible options are PULL_MODE (the default) and PUSH_MODE. It can be constrained.
Yes
See also “BFM-Driver Interaction Mode” on page 5-44. max_random_count: int
Used in setting the maximum number of subsequences in a RANDOM or MAIN sequence.
No
keep soft max_random_count == MAX_RANDOM_COUNT; // Defined to // be 10
max_random_depth: int
Used for setting the maximum depth inside RANDOM sequences. (Beyond that depth, RANDOM creates only SIMPLE sequences.)
No
keep soft max_random_depth == MAX_RANDOM_DEPTH; // Defined // to be 4
num_of_last_items: int
e Reuse Methodology
Used for setting the length of the history of previously sent items. Default is 1.
Yes
5-91
Sequences: Constructing Test Scenarios Sequence Interface
Table 5-4
any_sequence_driver Interface (continued) BFM Only
Struct Member
Description
gen_and_start_main: bool
Enable or disable automatic generation and launch of the MAIN sequence upon run. Default is TRUE (MAIN sequence is generated and started).
No
check_is_relevant()
For forcing a driver to recheck the relevance (value 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.
Yes
delay_clock() @sys.any
This TCM can be used to emit the driver’s clock with some intercycle delay to let the BFM export its state before activation of sequences in a specific cycle.
No
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 formula by users during the sequence driver hooking.
No
event item_done
Synchronization event for the do action in 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().
Yes
See also “Sequence Driver Unit” on page 5-7. get_sub_drivers(): list of any_sequence_driver is empty
For virtual sequence drivers, this method is to be filled in by the writer of the specific sequence 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.
Virtual only
read(address: list of bit): list of bit @clock is undefined;
For implementing a DUT-independent interface.
No
See also: “DUT-Independent Read/Write Interface” on page 5-41
5-92
e Reuse Methodology
Sequences: Constructing Test Scenarios Predefined Sequence Kinds
Table 5-4
any_sequence_driver Interface (continued)
Struct Member
Description
BFM Only
regenerate_data() is empty
Regenerates driver’s data upon rerun().
No
See also “Resetting and Rerunning Sequences” on page 5-39. send_to_bfm(seq_item: item_name) @clock is empty
When working in PUSH_MODE, sends the item to the corresponding BFM. To be implemented by users as part of hooking.
Yes
This method is called automatically (when working in PUSH_MODE). wait_for_sequences() @sys.any
This TCM is called to delay the return of 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.
Yes
write(address: list of bit, data: list of bit) @clock is undefined;
For implementing a DUT-independent interface.
No
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-94
e Reuse Methodology
5-93
Sequences: Constructing Test Scenarios MAIN Sequence
• “RANDOM Sequence” on page 5-94 • “SIMPLE Sequence” on page 5-95
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 keep keep keep
soft count > 0; soft count <= MAX_RANDOM_COUNT; sequence.kind not in [RANDOM, MAIN]; 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-94
e Reuse Methodology
Sequences: Constructing Test Scenarios SIMPLE Sequence
5.16.3
SIMPLE Sequence
This sequence subtype generates and executes a single item. 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-96 • “do Subsequence Flow” on page 5-97 • “do Item Flow in Push Mode” on page 5-98 • “do Item Flow in Pull Mode Using get_next_item()” on page 5-99 • “do Item Flow in Pull Mode Using try_next_item()” on page 5-100
e Reuse Methodology
5-95
Sequences: Constructing Test Scenarios sequence.start_sequence() Flow
5.17.1 Figure 5-9
sequence.start_sequence() Flow 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 does not schedule sequences but only items. Therefore, when starting a sequence, no synchronization is done between the driver and the started sequence.
emit @started.
Start TCM that:
- Calls pre_body() TCM - Calls body() TCM - Calls post_body() TCM
emit @ended.
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-76.
5-96
e Reuse Methodology
Sequences: Constructing Test Scenarios do Subsequence Flow
5.17.2 Figure 5-10
do Subsequence Flow do Subsequence Flow Sequence Driver (driver) (1)
Sequence (n) do subsequence
The sequence driver does not schedule sequences but only items. Therefore, when do-ing a sequence, no synchronization is done between the driver and the doing sequence or the done subsequence.
Call pre_do() TCM, with is_item = FALSE Generate subsequence with: - parent_sequence = sequence - driver = sequence.driver (by constraint)
subsequence is added to the driver’s trace list
Trace: “subsequence created” Call mid_do() Emit @subsequence.started Call subsequence.body() 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-97
Sequences: Constructing Test Scenarios do Item Flow in Push Mode
5.17.3 Figure 5-11
do Item Flow in Push Mode do Item Flow in Push Mode
BFM (1)
Driver (1) Choose a do action to be executed on a first-come-first-served basis, considering grabbers, and sequence.is_relevant() Acknowledge the sequence
Sequence (n) do item The do action is listed in the driver’s queue Wait for the driver acknowledgement Call pre_do() TCM, with is_item = TRUE Generate item with: - parent_sequence = sequence - driver = sequence.driver (by constraint)
Wait until item is generated
Sends item to DUT
Call send_to_bfm(item) Emit @item_done
item is added to the driver’s trace list” Trace: “item created” Call mid_do() Add item to driver’s last() buffer Acknowledge the driver that item is ready to be sent 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-98
e Reuse Methodology
Sequences: Constructing Test Scenarios do Item Flow in Pull Mode Using get_next_item()
5.17.4 Figure 5-12
do Item Flow in Pull Mode Using get_next_item() do Item Flow in Pull Mode Using get_next_item()
BFM
Driver
Sequence
Call driver.get_next_item() Choose a do action to be executed on a first-come–first-served basis, considering grabbers, and sequence.is_relevant() Acknowledge the sequence
do item The do action is listed in the driver’s queue Wait for the driver acknowledgement Call pre_do() TCM, with is_item = TRUE Generate item with: - parent_sequence = sequence - driver = sequence.driver (by constraint)
Wait until item is generated
Sends item to DUT Emit @item_done
Get next_item() returns
item is added to the driver’s trace list” Trace: “item created” Call mid_do() Add item to driver’s last() buffer Acknowledge the driver that item is ready to be sent 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-89.
e Reuse Methodology
5-99
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: { choose a do action } { wait_for_sequences() } A do action is chosen before wait_for_sequences returns?
Call driver.try_next_item()
No
Yes
try_next_item() Create a default item
returns with NULL
Send item to the DUT
Notes
• •
Continue as in
get_next_item() flow.
try_next_item() returns an item.
This flow occurs when driver.bfm_interaction_mode == PULL_MODE try_next_item() might take more than a cycle, in case a do is chosen 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-52 and Table 5-4 on page 5-89.
5.18 Sequence Deprecation • “Method sequence.start() Deprecation” on page 5-101 • “Field sequence Deprecation” on page 5-101 • “Sequence item Deprecation” on page 5-103 5-100
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-101
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-102
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-103 • “Item Children Cannot Be Created with Like Inheritance before Sequence Statement” on page 5-104 • “Sequences Are Supported Only from Version 4.1” on page 5-104
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-103
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-104
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. The three most typical uses for messages are:
e Reuse Methodology
6-1
Messaging Messaging Requirements
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 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 Figure 6-2
How Loggers Relate to Message Actions eVC with Screen and File Loggers
vr_xbus.elog
sys logger (NORMAL (LOW) => screen)
vr_xbus_env_u logger (NORMAL (FULL) => screen) file_logger (VR_XBUS_FILE (HIGH) => vr_xbus.elog)
foo()@clock message message message };
This message:
• •
Goes to file_logger (accepts the tag) Does not go to sys.logger (accepts
is { only NORMAL tag) (LOW, "Reset…"); (FULL, "Packet…"); (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 recognizes its tag (scanning from origin unit up to sys)
•
Other loggers will not see it (unless they send to a unique destination)
vr_xbus.elog
sys logger (NORMAL (FULL) => screen)
vr_xbus_env logger (NORMAL (LOW) => screen) file_logger (VR_XBUS_FILE (HIGH) => vr_xbus.elog)
foo()@clock message message message };
6.2.2.5
This message will not be shown. It is disabled for vr_xbus_env.logger and will not continue to sys.logger because of the above rules
is { (LOW, "Reset…"); (FULL, "Packet…"); (VR_XBUS_FILE, MEDIUM, "RESET: …");
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 tags, screen messages from this unit continue to sys.logger
left_xbus.elog
sys
right_xbus.elog
logger (NORMAL (MEDIUM) => screen)
soc_env_u logger (no tags=> screen) vr_xbus_env_u
vr_xbus_env_u
logger (NORMAL (FULL) => screen)
logger (no tags=> screen)
This message action is being filtered
file_logger (VR_XBUS_FILE (HIGH) => left_xbus.elog) file_logger (VR_XBUS_FILE (HIGH) => right_xbus.elog)
foo()@clock is { message (LOW, "Reset…"); message (FULL, "Packet…"); message (VR_XBUS_FILE, MEDIUM, "RESET: …"); };
6.2.2.6
foo()@clock is { message (LOW, "Reset…"); message (FULL, "Packet…"); message (VR_XBUS_FILE, MEDIUM, "RESET: …"); };
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 show message –l=all -full show message –actions
6.3
// Shows summary of all loggers // Shows full details per logger // Shows all message actions in files
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 always want to see. (This level cannot be disabled.)
“WARNING: Running in reduced mode”
LOW
Messages that happen once per run or once per reset.
“Master M3 was instantiated”
Short messages that happen once per data item or sequence.
“Packet-@36 was sent to port 7”
More detailed per-data-item information, including:
“Full details for packet-@36: len=5 kind=small ...”
MEDIUM
HIGH
• Printing the actual value of the packet
“Device D6 got out of reset”
“A write request to pci bus 2 with address=0xf2223, data=0x48883”
• 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. 2.
Removes from the list of handling loggers all loggers that ignore the message tag.
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] -flush_frequency=num
Specify the file flush_frequency for the logger.
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] [=tags|=all]
Force the logger to ignore the specified tags.
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 set message -add LOW
// Remove all // 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_time(): string Return the value and color of “[sys.time]”, for example, “[5]” 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= ) var style := get_action_style(); if (style != BLACK) { msg = vt.text_style(style,msg); };
6-36
e Reuse Methodology
Messaging Configuring Loggers via Constraints
var current_struct := source_struct(); var short_name_path := current_struct.get_unit().short_name_path(); 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:
e Reuse Methodology
6-37
Messaging Constrainable Fields and Their Default Values
• “Constrainable Fields and Their Default Values” on page 6-38 • “Using the Constrainable Fields to Configure Loggers” on page 6-38 • “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. 6-38
e Reuse Methodology
Messaging Constraining Verbosity
extend message_logger { // On post_generate(), configure the message logger according to fields 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}; };
e Reuse Methodology
6-39
Messaging The short_name_path() of a Unit
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: 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
6-40
e Reuse Methodology
Messaging How short_name_path() Works
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.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.
e Reuse Methodology
6-41
Messaging Colors for Message Actions
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.
• 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).
6-42
e Reuse Methodology
Messaging any_unit.short_name_style()
Note These colors apply only to text going to screen. Text going to file is scrubbed of color information.
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 e Reuse Methodology
6-43
Messaging Screen Logger
• “Special Tags” on page 6-48 • “Tracing Sequences” on page 6-48 • “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-71
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.1 Table 7-1
Packaging and Name Space Compliance Checks Packaging and Name Space Compliance Checks RQ/ RC/ ST
Index
Check
PKCL
Loading with golden eVC— Does the eVC run properly with the golden eVC loaded?
RQ
PKCT*
Configuration template— Are there config templates in the examples directory?
RQ
PKDF
Valid distribution format— Is the package distributed as package_version_version.tar.gz?
RQ
PKDN*
Valid ‘define’ name— Do all ‘define’ names have a legal package prefix?
RQ
PKDR
Demo script running— Does it run OK?
RQ
Demo script availability— Does the package have a demo.sh file to demonstrate the package, located at the top level of the package?
RQ
Enum extensions— If an enum from some other package is extended, do the new values start with the package prefix?
RQ
PKDS*
PKEE*
7-2
ER
3
Comments/ Information
See “evc/examples/” on page 3-3.
See “Handling Package Versions” on page 2-12. 3
See “Choosing a Package Name” on page 2-3. See “demo.sh File” on page 2-8.
See “demo.sh File” on page 2-8.
3
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/ ST
Check
PKEN*
Package encapsulation— Does all the code of the eRM package belong to one or more e packages (other than main)?
RQ
See “Packages as e Concept” on page 2-2.
PKER*
Examples documented— Is there a EXAMPLES_README.txt file in the examples directory detailing the contents?
RQ
See “Examples Directory” on page 2-8.
PKEX*
Examples documented—details— Are all examples documented?
RQ
See “Examples Directory” on page 2-8.
PKFN*
Valid file names— Do all source code filenames in the package start with the package name?
RQ
3
PKGE*
Global extends— Are there no extends to sys or global?
RC
3
PKGN*
Global extends naming— If sys or global is extended, are the extensions prefixed with the package prefix?
RQ
3
PKIM*
Import statements— Do all import statements refer to imported files using local or package-relative path?
RQ
PKLD*
Legal directory name— Is the package directory named consistently with the package name?
RQ
PKLN*
Legal package name— Does the package have a legal package name including company prefix and a unique intra-company package name?
RQ
e Reuse Methodology
ER
Comments/ Information
Index
See “File Naming Guidelines” on page 3-4.
See “Importing Files” on page 3-7.
3
See “Package-Related Naming Conventions” on page 2-3. See “Package-Related Naming Conventions” on page 2-3.
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/ ST
Check
PKMP*
Multiple packages— If there is more than one e package, do they all have the same prefix?
RQ
PKPN*
Package name— Does the top file belong to an e package whose name is identical to the eRM package?
RQ
See “Choosing a Package Name” on page 2-3.
PKPR*
Protection— How many public and non-public named types and members are there?
ST
Types and struct members—public and non-public.
PKSD
Simulator support documented— Are the simulators supported by the package documented in the manual?
RQ
See “PACKAGE_README.txt File” on page 2-19.
PKSS
Simulator support— Are the simulators supported by the demo documented in the PACKAGE_README.txt file?
RQ
See “PACKAGE_README.txt File” on page 2-19.
PKTE*
Type extensions— Do all extensions to types defined outside the package have fields that start with legal package prefix?
RQ
PKTF
Tar file— Is the tar file named and organized according to eRM standards?
RQ
PKTN*
Valid type names— Do all type names have a legal package prefix?
RQ
3
Include types, structs, and units. See “Choosing a Package Name” on page 2-3.
PKTP*
Top file— Is the top-level file of the eVC placed in the e subdirectory and called package_top.e?
RQ
3
Check the file has only imports and defines, and it has the version definition. See “e Directory” on page 2-8.
7-4
ER
Comments/ Information
Index
3
See “Choosing a Package Name” on page 2-3.
See “Handling Package Versions” on page 2-12.
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/ ST
ER
Comments/ Information
Index
Check
PKVD*
Valid directory structure— Is the package’s directory structured correctly
RQ
3
Is the package's directory structured correctly (for example, e, examples, docs directories as a minimum)? See “Directory Structure” on page 2-5.
PKVN*
Version number— Does the version number in PACKAGE_README.txt file match the version number in the top file?
RQ
3
Versioning done OK package version in PACKAGE_README 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— Is there a legal PACKAGE_README.txt file at the top level of the package?
e Reuse Methodology
RQ
3
See “Shipping New Versions of a Package” on page 2-13.
7-5
eVC Standardization Using eRM Compliance Checks Architecture Compliance Checks
7.2 Table 7-2
Architecture Compliance Checks Architecture Compliance Checks RQ/ RC/ ST
ER
Comments/ Information
Index
Check
ARAA*
Active agents— Do all ACTIVE agents have a BFM in them?
RQ
3
Active agents that contain other agents are not required to have a BFM in them. See “Agent Types” on page 4-25.
ARAC*
Agent names— Do all agents have a “name” field?
RQ
3
See “A Look at Agents” on page 4-6.
ARBF*
BFM— Are all BFMs instantiated in ACTIVE agents?
RQ
3
“BFM only in active agents” means: this agent has an “active_passive” field and the BFM is instantiated within its “when ACTIVE” subtype. See “Sub-Entities” on page 4-24.
ARBS
BFM driving signals— Are all DUT signals driven only by BFMs?
RQ
3
See “DUT and eVC” on page 4-2.
ARHW
HW access— Is all HW access done via signals defined in signal maps or “sig_” strings?
RQ
3
See “Terminology” on page 4-23.
ARIN*
Instantiation— Are all agents instantiated in envs or other agents?
RQ
3
See “DUT and eVC” on page 4-2.
ARMN*
Monitors— Are all monitors in envs or agents?
RQ
3
See “Modeling FAQs” on page 4-22.
ARNM*
eVC name— Does the env have a “name” field?
RQ
3
See “Instance Names and IDs” 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/ ST
ER
Comments/ Information
Index
Check
ARSA*
BFM Sequence drivers in ACTIVE agents— Are all BFM sequence drivers in ACTIVE agents?
RQ
3
See “A Look at Agents” on page 4-6.
ARSC
Scoreboarding— Are hooks provided for scoreboarding?
RC
3
See “Adding Scoreboards” on page 9-12.
ARSD*
ACTIVE agents with BFM sequence drivers— Do all ACTIVE agents have a BFM sequence driver?
RQ
3
Active agents that contain other agents are not required to have a BFM sequence driver in them. See “A Look at Agents” on page 4-6.
ARSG*
Signal definition— Are there signals (defined in a signal_map unit or defined with a “sig_” prefix in env or agent units)?
RC
3
List the signals defined in other units, for example, BFM or monitor. See “DUT Signals” on page 4-6.
ARSM*
Signal map instantiation— Are there signal maps defined? Are they all within agents and env units?
RC
7.3 Table 7-3
See “Components of Agents” on page 4-8.
Reset Compliance Checks Reset Compliance Checks
Index
Check
RSCG
Clock generator— Does the package provide a (sufficiently programmable) clock generator?
e Reuse Methodology
RQ/ RC/ ST
ER
RQ
3
Comments/ Information Qualified and unqualified clocks See “Reset Methodology” on page 9-2.
7-7
eVC Standardization Using eRM Compliance Checks Reset Compliance Checks
Table 7-3
Reset Compliance Checks (continued) RQ/ RC/ ST
ER
Comments/ Information
Index
Check
RSCH
Reset checks— Are there sufficient checks to ensure that the DUT behaves correctly after reset is de-asserted
RQ
3
See “Reset Methodology” on page 9-2.
RSDC
Working with DUT supplied clock— Does the package work with DUT supplied clock?
RQ
3
See “Reset Methodology” on page 9-2.
RSMR
Multiple resets— Does the package manage multiple resets during the test?
RQ
3
RSPR
Programmable resets— Does the package provide a mechanism for generating programmable reset(s) and can this feature be disabled?
RC
3
RSRC
Multiple reset checks— Are there sufficient specific checks relating to the DUT's response to assertion/de-assertion of reset?
RQ
RSRS
Reset support— Does the package correctly respond to resets (of any length) generated within the DUT at the start of the test
RQ
3
See “Supporting Multiple Resets” on page 9-1.
RSUC
Use of clocks— Which parts are running on unqualified clock?
ST
3
See “Reset Methodology” on page 9-2.
7-8
Name a test that shows multiple resets, and a coverage point which checks for multiple resets. See “Supporting Multiple Resets” on page 9-1.
e Reuse Methodology
eVC Standardization Using eRM Compliance Checks Checking Compliance Checks
7.4 Table 7-4
Checking Compliance Checks Checking Compliance Checks RQ/ RC/ ST
ER
Index
Check
CHCE*
Checks and expects— How many checks and expects are there?
ST
3
CHDE*
DUT errors— How many dut_errors were defined?
ST
3
CHDM*
DUT error messages— Do all expects and checks have non-default dut_error message?
RQ
3
CHED
Error message documentation— Are all checks (both for DUT errors and user errors) sufficiently documented?
RQ
3
CHEM
Error messages— Do all error messages provide sufficient detail for the user to identify the area and instance of the package/DUT that produced the error?
ST
3
CHEX*
Named expects— Are all expects named?
RC
CHPC
Protocol checking— Does the package provide sufficient DUT checking (for example, protocol checkers) to cover all possible DUT errors?
RQ
3
CHSC
Scoreboard— Does the package provide (where 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?
RC
3
e Reuse Methodology
Comments/ Information
Where in the manual are they documented?
See “Adding Scoreboards” on page 9-12.
7-9
eVC Standardization Using eRM Compliance Checks Coverage Compliance Checks
7.5 Table 7-5
Coverage Compliance Checks Coverage Compliance Checks RQ/ RC/ ST
ER
Index
Check
CVCG*
Coverage groups— How many coverage groups are defined?
ST
3
CVCI*
Coverage items— How many coverage items are defined?
ST
3
CVCR*
Coverage crosses— How many coverage crosses are defined?
ST
3
CVRS
Coverage results— Is the coverage report produced after testing this eVC included in the package?
RQ
3
7.6 Table 7-6
Preferred approach: Supply the ecov files and a shell script called “show_cover.sh”, all in a directory called package/ coverage. Alternative approach: provide an ASCII coverage report.
Sequences Compliance Checks Sequences Compliance Checks RQ/ RC/ ST
ER
Index
Check
SQEI
Error injection— Do the sequence items provide sufficient ability to inject errors into the generated data stream(s)?
RQ
3
SQPT*
Predefined sequence types— How many predefined sequence types are provided?
ST
3
7-10
Comments/ Information
Comments/ Information
For each SD type, how many “kinds” of sequences are defined in it (other than the 3 default ones), that is, how big is the sequence library? e Reuse Methodology
eVC Standardization Using eRM Compliance Checks Sequences Compliance Checks
Table 7-6
Sequences Compliance Checks (continued)
Index
Check
SQRW*
Read/Write methods— How many sequences have their read()/write() methods extended?
RQ/ RC/ ST RC / ST
ER 3
Comments/ Information For SDs that represent read/write operations, we 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— Do all virtual sequence drivers have subdrivers?
RC
3
See “Creating a Virtual Sequence” on page 5-26.
SQSS*
SD statistics— How many sequence drivers exist? How many of them are BFM/virtual?
ST
3
See “Using Virtual Sequences” on page 5-25.
SQVF
Error injection—virtual fields— Are virtual fields appropriately employed?
RC
3
SQVP*
Virtual sequence driver (SD) pointers— Do virtual sequence drivers have pointers to one or more other sequence drivers?
RQ
3
See “Using Virtual Sequences” on page 5-25.
SQWR*
Read/Write wrappers— How many sequence drivers implement read()/write() methods?
ST
3
See “DUT-Independent Read/Write Interface” on page 5-41.
e Reuse Methodology
7-11
eVC Standardization Using eRM Compliance Checks Messaging Compliance Checks
7.7 Table 7-7
Messaging Compliance Checks Messaging Compliance Checks RQ/ RC/ ST
Check
MSFL*
File loggers— Are there file loggers defined in the package?
RC
MSLC
Logger constraints— Are all loggers constrained using only soft constraints?
RC
MSLG*
Loggers— Is there a screen logger in the env and in each agent?
RQ
MSLI*
Logger instantiation— Are all message loggers instantiated in env units, agents monitors or in sys?
RQ
3
See “Message Loggers” on page 6-20.
MSMA*
Message actions— How many message actions are there? At what verbosity levels are these actions?
ST
3
See “The Message Action” on page 6-16.
MSMT*
Message tags— How many message TAGs were defined?
ST
3
See “message_tag” on page 6-20.
MSSN*
Short name and short name style— Do short_name() and short_name_style() return non-empty strings?
RC
3
7-12
ER
Comments/ Information
Index
See “File Logger(s)” on page 6-44. 3
See “Soft Constraints” on page 6-49. See “Screen Logger” on page 6-44.
See “any_unit.short_name_style()” on page 6-43.
e Reuse Methodology
eVC Standardization Using eRM Compliance Checks Monitor Compliance Checks
7.8 Table 7-8
Monitor Compliance Checks Monitor Compliance Checks
Index
Check
MNEE
Error extraction— 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.9 Table 7-9
RQ/ RC/ ST
ER
ST
3
Comments/ Information
Documentation Compliance Checks Documentation Compliance Checks RQ/ RC/ ST
Index
Check
DCBF
BFM documentation— Are all BFMs documented (API and behavior)?
RQ
DCCF
Constrainable fields— Does the documentation describe all user-constrainable fields and indicate when they are generated and what default constraints are applied to them?
RQ
DCDC*
Documentation— Which documentation files exist in the /docs directory (.doc, .pdf)?
RQ
DCEX
Examples— Does the documentation give sufficient examples to cover the most likely user scenarios?
RQ
e Reuse Methodology
ER
Comments/ Information
Check /docs directory for .doc, .pdf, .fm. See “Docs Directory” on page 2-8.
7-13
eVC Standardization Using eRM Compliance Checks Documentation Compliance Checks
Table 7-9
Documentation Compliance Checks (continued) RQ/ RC/ ST
Index
Check
DCFC
Features and controls— Does the documentation cover all features and controls?
RQ
DCFM
Documentation format— 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?
RC
DCID
Installation and demo— Does the documentation describe the installation and demo processes?
RQ
DCPA
Package architecture— Does the documentation describe the architecture of the package and give an overview of its intended use?
RQ
DCPR
Proper documentation— Are concepts introduced before being referred to?
RC
DCRN*
Release notes— Are release notes provided in the docs directory?
RQ
DCRP
Recommended practice— 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)?
RQ
DCRS
Reset— Does the documentation explain whether the package manages multiple resets during the test?
RQ
7-14
ER
Comments/ Information
Suffix .txt, .pdf, .doc, .rtf.
e Reuse Methodology
eVC Standardization Using eRM Compliance Checks General Deliverables Compliance Checks
Table 7-9
Documentation Compliance Checks (continued) RQ/ RC/ ST
Index
Check
DCSD
SD documentation— Are all sequence-driver test interfaces sufficiently documented?
RQ
DCSP
Support policies— Does the documentation clearly define the support polices for the package and indicate contact information for obtaining support?
RQ
DCST
eVC structure— 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.
RQ
DCUF
Usable fields— Does the documentation describe all non-user-constrainable fields that users may use to control their constraints?
RQ
ER
Comments/ Information
7.10 General Deliverables Compliance Checks Table 7-10
General Deliverables Compliance Checks RQ/ RC/ ST
Index
Check
GDCF
Customer feedback— Number of customer engagements this eVC has been involved in. Provide customer quotes or feedback indicating satisfaction level, likes and dislikes if available.
RQ
GDCL*
Code lines— How many lines of code are there?
ST
e Reuse Methodology
ER
3
Comments/ Information
Statistics with and without comment lines. 7-15
eVC Standardization Using eRM Compliance Checks Visualization Compliance Checks
Table 7-10
General Deliverables Compliance Checks (continued) RQ/ RC/ ST
ER
Comments/ Information
Index
Check
GDNF
New functionality— New functionality added since previous release.
RQ
Not applicable for first release, should refer to release notes.
GDNM
eVC name
RQ
As defined in the user manual.
GDPN
Protocol name and version— Name and version number of protocol or architecture the eVC models.
RQ
GDSM
Support model— Description of the post sales support model for this eVC. (for example, on-site support for 7 days, then telephone support).
RQ
GDTP
Test plan— 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).
RQ
7.11 Visualization Compliance Checks Table 7-11
Visualization Compliance Checks
Index
Check
VT
Visualization
7-16
RQ/ RC/ ST
ER
Comments/ Information See Chapter 8 “The eRM Utility”.
e Reuse Methodology
eVC Standardization Using eRM Compliance Checks End of Test Compliance Checks
7.12 End of Test Compliance Checks Table 7-12
End of Test Compliance Checks
Index
Check
ET
End of test
RQ/ RC/ ST
ER
Comments/ Information See “Status Coordination and End of Test” on page 9-15.
7.13 Other Possible Compliance Checks Table 7-13
Index
Other Possible Compliance Checks
Check
RQ/ RC/ ST
ER
Comments/ 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 Figure 8-7
The Env Window 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 Figure 8-8
The Stripe Chart Window 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
8-10
Stripe Chart Window (Multi-Stream)
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 (name, version, and so on)
This information is returned as a list of string by the method 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
Method
Description
Parameters
Return Value
Methods of any_sequence_item
get_stripe_prefix()
Adds default implementation for stripe prefix.
s: vt_stripe
get_stripe_body()
Extended by the user to customize the stripe chart.
s: vt_stripe
By default, this method is empty. get_stripe_suffix()
Adds default implementation for stripe suffix.
s: vt_stripe
stripe()
Calls get_stripe_prefix(), get_stripe_body(), and get_stripe_suffix() to convert data item info into stripe info.
s: vt_stripe
create_visual_stripe()
Adds user-defined data items (for example, monitor items) to a list of items that can be shown as stripes. The particular list is determined by the given name. If the name is empty, the caller e_path() or to_string() is treated as the name.
caller: any-struct name: string t: time
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 that were directly called by the sequence.
list of any_ sequence_ item
get_env_basic_info()
Shows basic information in the Env window.
list of string
get_env_detailed_info()
Shows unit tree in the Env window.
list of string
Methods of any_env
e Reuse Methodology
8-15
The eRM Utility Controlling Messaging
Method
Description
get_env_stripe_chart_ info()
Shows stripe chart information in the Env window.
8.3
Parameters
Return Value list of string
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 logger with hyperlinks to each message logger’s individual Message Logger window.
Figure 8-11 on page 8-17
Message Logger
Shows detailed information for a specific message logger and lets you make on-the-fly changes to that logger’s settings for recognized message tags.
Figure 8-12 on page 8-18
Logger Destinations
Lists all available message destinations, showing for each its associated loggers. The logger hyperlinks open the relevant Message Logger window.
Figure 8-13 on page 8-19
Messages
Lists all messages with details on verbosity, tag, logger, and package. The message hyperlinks display the source code for that message.
Figure 8-14 on page 8-20
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 Figure 8-11
Controlling Message Loggers 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 Figure 8-13
The Logger Destinations Window 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 Figure 8-14
Controlling Messages 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 Figure 8-15
The eDoc Window 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 Figure 8-16
Generating eDoc Reports 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,
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 8-24
Sort report by order of loading. (The default is alphabetical order.) 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 • “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:
• Temporals: Graceful shutdown / rerun (events, expects, TCMs)
e Reuse Methodology
9-1
Reference Reset Methodology
• 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
The current reset methodology works as follows:
9-2
e Reuse Methodology
Reference Reset Methodology
• 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. • 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:
e Reuse Methodology
9-3
Reference rerun()
• 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
9.1.4
Reset Timing
Reset Example
extend xyz_env { event unqualified_clk is change('(sig_clock)') @sim;1 event clk is true('(sig_reset)'==DEASSERTED) @unqualified_clk; };
1. Define clocks.
extend xyz_env { event reset_start is fall('(sig_reset)') @sim; event reset_end is rise('(sig_reset)') @sim; };
2. Define reset events.
extend xyz_agent2 {
3. Propagate rerun() recursively.
on reset_start1 { 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 { main() @clk is {...}; // main TCM run() is also { start main(); }; }; extend xyz_agent_monitor { event data_phase is {@arb_phs; @addr_phs}@clk; expect true('(sig_start)' == 0) @data_phase; };
4. Define agent activity: TCMs and TEs that halt on reset.
extend xyz_env_monitor { expect @reset_start => {[3] * not @reset_end} @unqualified_clk; };
5. Reset checker: TEs that 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 Status Coordination and End of Test
9.4
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.4.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.4.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:
• 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.
e Reuse Methodology
9-15
Reference Introduction to Status Coordination
9.4.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.4.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-17
Main Methods of any_unit any_unit contains the following main methods (each of which gets objection_kind as a parameter):
• 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. 9-16
e Reuse Methodology
Reference Objection Mechanism
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.4.2
Objection Mechanism
This section explains the objection mechanism in detail. It includes:
• “objection_kind enum” on page 9-17 • “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 • “Debugging Aids” on page 9-21
9.4.2.1
objection_kind enum
The predefined enum type objection_kind contains all topics for which the objection mechanism is needed.
e Reuse Methodology
9-17
Reference Objection Mechanism
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.4.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.4.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: objection_kind)
This extensible method is initially empty, except 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: objection_kind): int
Returns the objection counter for the unit, that is, the current number of objections to objection_kind in the unit itself, regardless of its subunits.
get_objection_total(kind: objection_kind): int
Returns the objection total of the unit, that is, the total number of objections to objection_kind in the tree that includes both the unit itself and all of its subunits.
get_objection_list(kind: objection_kind): list of any_unit
Returns the list of units directly under the unit (not including it) for which the objection total is not zero.
e Reuse Methodology
9-19
Reference Objection Mechanism
Example Figure 9-3 Unit A
Objection Status Example
Counter : 1 Total : 8
Unit B
Counter : 5 Total : 5
Unit C
Counter : 0 Total : 0
Unit D
Counter : 0 Total : 2
Unit E
Counter : 1 Total : 1
Unit F
Counter : 0 Total : 0
Unit G
Counter : 1 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.4.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.4.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 %-5s %-7s \n", u.get_objection_counter(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.4.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.4.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.4.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.4.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.5
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.5.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.5.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
9-26
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.
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.5.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.5.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.5.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-2.)
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.5 eVC Environment: Flexibility vs. Rigidity Flexibility is measured by two factors: 10-2
e Reuse Methodology
Golden eVCs How to Determine Environment Flexibility
• 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. They do not have to read the documentation to understand what can be controlled and how.
The environment tends to be safer for users. Working in the limited zone defined by the 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. keep tx_monitor.sig_clock == value(sig_tx_clock); 10-4
e Reuse Methodology
Golden eVCs Setting Environment Flexibility Using Generation Order
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 active agents 4-25 agents components 4-8 configuration 4-9 data item naming convention 4-25 definition 4-23 examples 4-25 in depth 4-6 internals 4-8 monitor 4-10 overview 4-7 sequence drivers 4-9 signals 4-9 types of 4-25 all_objections_dropped() 9-19 any_env unit 2-23 connecting to package 2-29 example 2-23 methods, user-visible 2-24 any_sequence, interface 5-87 any_sequence_driver, interface 5-89 any_sequence_item, interface 5-86 any_unit methods 9-18 methods, main 9-16 any_unit.short_name_style() 6-43 architecture eVC standardization, developer comments e Reuse Methodology
7-6 architecture diagrams, legend for brief 4-5 full 4-26 architecture diagrams, legend, definition 4-26 architecture, eVC, basic 4-1 at_message_verbosity recommended methodology 6-48 ATM eVC 10-2 auto_quit() 5-55
B BFM 4-10 BFM, definition 4-23 BFM-driver interaction mode 5-44 BFM-monitor guidelines 4-25 BFM-monitor relations 4-24 BFMs 4-5 body() TCM 5-12
C checker 4-11 checking eVC standardization, developer comments 7-9 clocks 4-6 clusters, file 3-7 color
Index-1
Index
handling in Specman Elite 6-42 message actions, whole recommended methodology 6-47 time 6-43 combining eVCs 4-14 commands show doc 8-24 show packages 2-26 commands, message 6-23 detailed explanation 6-25 summary 6-23 compliance checks architecture 7-6 checking 7-9 coverage 7-10 documentation 7-13 end of test 7-17 general deliverables 7-15 messaging 7-12 name space 7-2 other possible 7-17 packaging 7-2 reset 7-7 sequences 7-10 visualization 7-16 constraints, soft recommended methodology 6-49 coordination, status 9-15 any_unit methods 9-18 conversion, old code 9-25 debugging 9-17, 9-21 introduction 9-15 methods, any_unit 9-18 objection status example 9-20 old code, conversion of 9-25 overview 9-16 requirements 9-15 solution 9-17 coverage 4-11 default eVC coverage 4-11 eVC standardization, developer comments 7-10 Index-2
current_grabber() 5-81 cyclic dependencies 3-8 alternative approach 3-9
D data item, definition 4-23 debug output display, customizing 5-75 definitions 4-23 agent 4-23 architecture diagrams, legend 4-26 BFM 4-23 data item 4-23 DUT 4-23 monitor 4-23 package 4-23 demo.sh file 2-8 dependencies on package versions, handling 2-15 on Specman Elite release, handling 2-15 dependencies, cyclic 3-8 alternative approach 3-9 DEPR_MESSAGE_LOGGER 6-4 DEPR_SEQUENCE_ITEM_KEYWORD 5-103 DEPR_SEQUENCE_START_KEYWORD 5-101 deprecation message logger structs 6-4 sequence field 5-101 sequence item 5-103 sequence.start() 5-101 diagram language 4-4 directories docs directory 2-8 e directory 2-8 examples directory 2-8 library directory 2-7 other 2-10 self-verification directory 2-9 structure 2-5 directories, eVC source subdirectories 3-2 do 5-13 e Reuse Methodology
Index
do item flow, pull mode, using get_next_item() 5-99 do item flow, pull mode, using try_next_item() 5-100 do item flow, push mode 5-98 do subsequence flow 5-97 documentation eVC standardization, developer comments 7-13 drop_objection() 9-18 DUT, definition 4-23 DUT, example 4-2
E e directory 2-8 eDoc 8-21 eDoc window 8-22 output 8-23 report 8-23 report input 8-23 using 8-21 eDoc window 8-22 encryption 9-25 end of test 9-15, 9-22 eVC standardization, developer comments 7-17 handling complex 9-24 examples 9-23 requirements 9-16 via sequences 9-23 simple 9-23 introduction 9-15 solution 9-17 end-of-test basic 9-23 end-to-end scoreboards 9-13 enumerated logical names 9-7 env, definition 4-23 eRM compliance checks 7-1 eRM release library 1-2 erm_lib 1-2 eVC architecture, basic 4-1 e Reuse Methodology
eVC architecture, typical 4-1 eVC example combining eVCs 4-14 complex 4-12 simple 4-2 eVC standardization 7-1 checking 7-9 coverage 7-10 developer comments architecture 7-6 documentation 7-13 end of test 7-17 general deliverables 7-15 messaging 7-12 monitor 7-13 name space 7-2 other possible sections 7-17 packaging 7-2 reset 7-6 sequences 7-10 visualization 7-16 reset 7-7 evc/docs/ 3-3 evc/e/ 3-2 evc/examples/ 3-3 evc_util package 2-4 eVCs 1-3 defined 1-3 plug-and-play 1-5 reuse requirements 1-5 VEs, versus 1-4 eVCs, golden 10-1 ATM eVC 10-2 XBus eVC 10-1 XSerial eVC 10-2 XSoc eVC 10-2 events 4-6
F FAQs, modeling 4-22 file names, package-relative, using 2-10 files cyclic dependencies 3-8 Index-3
Index
files, accessing 2-10 files, eVC clusters 3-7 cyclic dependencies, alternative approach 3-9 importing 3-7 naming guidelines 3-4 partitioning source into 3-3
G general deliverables eVC standardization, developer comments 7-15 get_objection_counter() 9-19 get_objection_status() 9-19 golden eVCs 10-1 ATM eVC 10-2 XBus eVC 10-1 XSerial eVC 10-2 XSoc eVC 10-2 grab() 5-78
I IDs 9-6 importing files 3-7 in_sequence() 5-84 in_unit() 5-85 instance names 9-6 XBus Example 9-9 instance names and IDs 9-6 uses of 9-8 instantiating entities 3-5 is_blocked() 5-80 is_grabbed() 5-81 is_relevant() 5-55, 5-82
L language, diagram 4-4 last() 5-82 layer connection process 4-18 layering Index-4
late binding 5-68 low-layer sequence 5-66 solution overview 5-64 layering eVCs 4-15 layering, protocols 5-56 basic layering 5-60 data control 5-62 different configurations at elaboration time 5-61 general case 5-63 introduction 5-57 many-to-many 5-61 many-to-one 5-61 one-to-many 5-61 one-to-one 5-61 styles of layering 5-59 timing control 5-62 library, release, eRM 1-2 logger file recommended methodology 6-44 screen recommended methodology 6-44 loggers concerned 6-21 constrainable fields 6-38 examples 6-39 fields, constrainable, how used 6-38 messages, handling 6-21 logical names, enumerated 9-7
M message action 6-16 examples 6-17 message_tag 6-20 output appearance 6-18 semantics 6-17 syntax 6-16 verbosity, recommended usage 6-19 message loggers 6-20 struct deprecation 6-4 message messages 6-1 message output e Reuse Methodology
Index
time, scaling 6-51 message_logger extending recommended methodology 6-51 message_logger methods 6-33 called while handling messages 6-34 configuration, setting 6-33 configuration, showing 6-34 query for message information 6-35 message_tag 6-20 messaging 6-1 colors for message actions 6-42 computing the short_name_path() of a unit 6-40 eVC standardization, developer comments 7-12 loggers, configuring via constraints 6-37 methodology, recommended 6-43 procedural interface 6-33 requirements 6-2 solution 6-3 messaging commands 6-23 when to issue recommended methodology 6-49 modeling, FAQs 4-22 monitor checking 4-10 coverage 4-10 eVC standardization, developer comments 7-13 global monitor 4-10 monitor, definition 4-23 monitor-BFM guidelines 4-25 monitor-BFM relations 4-24 monitors 4-5
N name space eVC standardization, developer comments 7-2 names, logical, enumerated 9-7 nice_string() 5-75 non-env utilities, instantiating 2-29 e Reuse Methodology
O objection 9-17 all_objections_dropped() 9-19 any_unit methods 9-18 counter 9-18 drop_objection() 9-18 get_objection_counter() 9-19 get_objection_total() 9-19 objection counter 9-18 objection total 9-18 objection_kind enum 9-17 raise_objection() 9-18 total 9-18 objection_kind 9-16, 9-17 objection_kind enum 9-17
P package, definition 4-23 PACKAGE_README.txt file 2-7, 2-19 examples 2-20 headers 2-19 location 2-19 packages checking legality 2-22 defining a verification component package 2-1 as e concept 2-2 evc_util 2-4 file names, package-relative, using 2-10 importing files within same e source directory 2-11 kinds of 2-2 naming conventions 2-3 package directory 2-7 package name, choosing 2-3 packing simple way 2-14 readme file 2-7, 2-19 description 2-19 examples 2-20 headers 2-19 location 2-19 Index-5
Index
receiving libraries 2-28 shadowing 2-11 shipping libraries 2-28 shipping new versions 2-13 verification component package, definition 2-1 version dependencies 2-15 version number 2-12 versions, handling 2-12 packaging eVC standardization, developer comments 7-2 packing version, simple way 2-14 passive agents 4-25 pipelined protocols, handling 5-46 protocols, layering 5-56 basic layering 5-60 data control 5-62 different configurations at elaboration time 5-61 general case 5-63 introduction 5-57 many-to-many 5-61 many-to-one 5-61 one-to-many 5-61 one-to-one 5-61 styles of layering 5-59 timing control 5-62 protocols, pipelined 5-46 PUSH_MODE 5-45
Q quit(), behavior upon 9-20
R raise_objection() 9-18 reactive agents 4-25 readme file, packages 2-7, 2-19 description 2-19 examples 2-20 headers 2-19 location 2-19 Index-6
receiving packages, libraries 2-28 release library, eRM 1-2 rerun() 9-4 rerun(), behavior upon 9-20 reset eVC standardization, developer comments 7-7 multiple resets, supporting 9-1 reset methodology revisions 9-2 timing 9-5 resets, multiple requirements 9-1
S scalar IDs 9-8 scenarios implementing with sequence struct 5-12 scenarios See also sequences scoreboard definition 9-12 scoreboards adding 9-12 end-to-end 9-13 end-to-end hooks 9-13 memory access 9-13 recommendations 9-14 sequence drivers common base 5-50, 5-51 sequence field deprecation 5-101 sequence items quitting 5-55 sequence.item deprecation 5-103 sequence.start() deprecation 5-101 sequence.start() flow 5-96 sequences 5-1 common base 5-50, 5-51 complex scenarios, implementing 5-35 concurrent sequence kind, defining 5-36 configurations, before starting 5-37 constraining with unit IDs 5-24 e Reuse Methodology
Index
debugging 5-71 defining 5-5 defining behavior of 5-12 defining using the sequence statement 5-5 do action queue, forcing reevaluation 5-55 drivers, passing of 5-27 eVC standardization, developer comments 7-10 file organization 5-24 flow diagrams 5-95 flow of control and data 5-4 generating in advance 5-34 generation-related aspects, advanced 5-31 implementing 5-11 initializations, before starting 5-37 interface 5-86 interrupt sequences 5-37 introduction 5-2 limitations, known 5-103 same item cannot be used in two different sequences 5-103 sequences supported only from Specman Elite version 4.0 5-104 main 5-94 MAIN sequence 5-94 message recommended methodology 6-48 modifying 5-21 other drivers, making behave 5-28 parameterizing 5-16 parameters, propagating in sequence tree 5-33 quitting 5-55 random 5-94 RANDOM sequence 5-94 read/write interface, DUT-independent 5-41 rerunning 5-39 resetting 5-39 resources, locking 5-44 scenarios, advanced 5-35 scheduling of items, controlling 5-43 sequence driver, hooking to environment 5-9 sequence item, defining 5-5 e Reuse Methodology
sequence kinds, predefined 5-93 sequence library, creating 5-19 sequence-related methods 5-76 sequence-related pseudo-routines 5-84 SIMPLE sequence 5-94 simple sequences 5-94 for SoC 5-28 SoC sequence example 5-30 tracing 5-71 unit attributes, migrating 5-33 using in environment 5-4 virtual sequences, using 5-25 virtual, creating 5-26 writing tests 5-20 dedicated, creating new sequence kind 5-23 random, setting weights 5-21 simple, by redefining main body() 5-20 typical, using sequence library 5-21 unit-related, using unit ID 5-23 set message 6-26 set message -file 6-29 set message filter 6-26 set message -flush_frequency 6-30 set message -format 6-30 set message -screen 6-30 set message -style 6-30 set message -units 6-28 shadow agents 4-25 shipping packages libraries 2-28 versions, new 2-13 short names handling recommended methodology 6-46 short_name() 6-41 short_name_path() 6-40 how it is computed 6-41 how it works 6-41 short_name() 6-41 show doc syntax 8-24 Index-7
Index
show message 6-31 show message -actions 6-32 recommended methodology 6-51 show message -logger 6-32 show message -units 6-32 show packages command 2-26 show packages, output example 2-26 show sequence 5-74 signals, DUT 4-6 sn_which.sh shell script 2-11 SoC designs, eVCs within 5-29 source subdirectories 3-2 start_sequence() 5-76 status coordination 9-15 any_unit methods 9-18 conversion, old code 9-25 debugging 9-17, 9-21 introduction 9-15 methods, any_unit 9-18 objection status example 9-20 old code, conversion of 9-25 overview 9-16 requirements 9-15 solution 9-17 stop() 5-77 styles handling recommended methodology 6-46 subdirectories, source 3-2 suffixes, adding to types 2-29 syntax show doc 8-24
T tags special recommended methodology 6-48 terminology 4-23 test en d handling complex 9-24 test end 9-15, 9-22 Index-8
basic 9-23 handling examples 9-23 requirements 9-16 via sequences 9-23 simple 9-23 introduction 9-15 solution 9-17 trace output display, customizing 5-75 trace sequence 5-71, 6-48 transactions 5-31
U ungrab() 5-79 unit IDs, hierarchical 5-24 user interface, enhancing 5-17
V verb tenses recommended methodology 6-49 verbosity-num verbosity levels 6-19 version number, packages 2-12 visualization eVC standardization, developer comments 7-16
W wave sequence 5-74
X XBus eVC 4-13, 10-1 XSerial eVC 4-2, 10-2 XSoC eVC 4-14, 10-2
e Reuse Methodology