Sie sind auf Seite 1von 602

Vera User Guide

Version X-2005.12 December 2005

Comments? E-mail your comments about Synopsys documentation to vera-doc@synopsys.com

Copyright Notice and Proprietary Information


Copyright 2006 Synopsys, Inc. All rights reserved. This software and documentation contain confidential and proprietary information that is the property of Synopsys, Inc. The software and documentation are furnished under a license agreement and may be used or copied only in accordance with the terms of the license agreement. No part of the software and documentation may be reproduced, transmitted, or translated, in any form or by any means, electronic, mechanical, manual, optical, or otherwise, without prior written permission of Synopsys, Inc., or as expressly provided by the license agreement.

Right to Copy Documentation


The license agreement with Synopsys permits licensee to make copies of the documentation for its internal use only. Each copy shall include all copyrights, trademarks, service marks, and proprietary rights notices, if any. Licensee must assign sequential numbers to all copies. These copies shall contain the following legend on the cover page: This document is duplicated with the permission of Synopsys, Inc., for the exclusive use of __________________________________________ and its employees. This is copy number __________.

Destination Control Statement


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

Disclaimer
SYNOPSYS, INC., AND ITS LICENSORS MAKE NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

Registered Trademarks ()
Synopsys, AMPS, Arcadia, C Level Design, C2HDL, C2V, C2VHDL, Cadabra, Calaveras Algorithm, CATS, CRITIC, CSim, Design Compiler, DesignPower, DesignWare, EPIC, Formality, HSIM, HSPICE, Hypermodel, iN-Phase, in-Sync, Leda, MAST, Meta, Meta-Software, ModelTools, NanoSim, OpenVera, PathMill, Photolynx, Physical Compiler, PowerMill, PrimeTime, RailMill, RapidScript, Saber, SiVL, SNUG, SolvNet, Superlog, System Compiler, TetraMAX, TimeMill, TMA, VCS, Vera, and Virtual Stepper are registered trademarks of Synopsys, Inc.

Trademarks ()
Active Parasitics, AFGen, Apollo, Apollo II, Apollo-DPII, Apollo-GA, ApolloGAII, Astro, Astro-Rail, Astro-Xtalk, Aurora, AvanTestchip, AvanWaves, BCView, Behavioral Compiler, BOA, BRT, Cedar, ChipPlanner, Circuit Analysis, Columbia, Columbia-CE, Comet 3D, Cosmos, CosmosEnterprise, CosmosLE, CosmosScope, CosmosSE, Cyclelink, Davinci, DC Expert, DC Expert Plus, DC Professional, DC Ultra, DC Ultra Plus, Design Advisor, Design Analyzer, Design Vision, DesignerHDL, DesignTime, DFM-Workbench, Direct RTL, Direct Silicon Access, Discovery, DW8051, DWPCI, Dynamic-Macromodeling, Dynamic Model Switcher, ECL Compiler, ECO Compiler, EDAnavigator, Encore, Encore PQ, Evaccess, ExpressModel, Floorplan Manager, Formal Model Checker, FoundryModel, FPGA Compiler II, FPGA Express, Frame Compiler, Galaxy, Gatran, HANEX, HDL Advisor, HDL Compiler, Hercules, Hercules-Explorer, Hercules-II, plus Hierarchical Optimization Technology, High Performance Option, HotPlace, HSIM , HSPICE-Link, iN-Tandem, Integrator, Interactive Waveform Viewer, i-Virtual Stepper, Jupiter, Jupiter-DP, JupiterXT, JupiterXT-ASIC, JVXtreme, Liberty, Libra-Passport, Library Compiler, Libra-Visa, Magellan, Mars, Mars-Rail, Mars-Xtalk, Medici, Metacapture, Metacircuit, Metamanager, Metamixsim, Milkyway, ModelSource, Module Compiler, MS-3200, MS-3400, Nova Product Family, Nova-ExploreRTL, Nova-Trans, Nova-VeriLint, Nova-VHDLlint, Optimum Silicon, Orion_ec, Parasitic View, Passport, Planet, Planet-PL, Planet-RTL, Polaris, Polaris-CBS, Polaris-MT, Power Compiler, PowerCODE, PowerGate, ProFPGA, ProGen, Prospector, Protocol Compiler, PSMGen, Raphael, Raphael-NES, RoadRunner, RTL Analyzer, Saturn, ScanBand, Schematic Compiler, Scirocco, Scirocco-i, Shadow Debugger, Silicon Blueprint, Silicon Early Access, SinglePass-SoC, Smart Extraction, SmartLicense, SmartModel Library, Softwire, Source-Level Design, Star, Star-DC, Star-MS, Star-MTB, Star-Power, Star-Rail, Star-RC, Star-RCXT, Star-Sim, Star-SimXT, Star-Time, Star-XP, SWIFT, Taurus, TimeSlice, TimeTracker, Timing Annotator, TopoPlace, TopoRoute, Trace-On-Demand, True-Hspice, TSUPREM-4, TymeWare, VCS Express, VCSi, Venus, Verification Portal, VFormal, VHDL Compiler, VHDL System Simulator, VirSim, and VMC are trademarks of Synopsys, Inc.

Service Marks (SM)


MAP-in, SVP Caf, and TAP-in are service marks of Synopsys, Inc. SystemC is a trademark of the Open SystemC Initiative and is used under license. ARM and AMBA are registered trademarks of ARM Limited. All other product or company names may be trademarks of their respective owners.

Vera User Guide, version X-2005.12

ii

Contents
Known Limitations and Resolved STARs . . . . . . . . . . . . . . . . . . . . About This Guide. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Customer Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1. Introduction Overview of Testbench Development . . . . . . . . . . . . . . . . . . . . . . . Components of a Basic Vera Verification Environment . . . . . . . . . . SystemClock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Template Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-3 1-4 1-7 1-7 xviii xviii xxii

Vera Interactive Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-10 Running Vera Standalone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-10 2. Using Vera The Vera Testbench Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Verilog-based Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . VCS Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-2 2-3 2-6

VHDL-based Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-11

iii

VHDL Example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-12 Simulator Specific Instructions . . . . . . . . . . . . . . . . . . . . . . . 2-16 Mixed HDL-based Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Use Models with Different Simulators. . . . . . . . . . . . . . . . . . VCS-MX (Verilog on top) . . . . . . . . . . . . . . . . . . . . . . . . . . . VCS-MX (VHDL on top) . . . . . . . . . . . . . . . . . . . . . . . . . . . . Simplified Use Model for VCS-MX . . . . . . . . . . . . . . . . . . . . ModelSim SE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . NC-Sim. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Limitations and Unsupported Features . . . . . . . . . . . . . . . . SystemC-based Flow. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating an OpenVera Interface. . . . . . . . . . . . . . . . . . . . . . Running SystemC with OpenVera . . . . . . . . . . . . . . . . . . . . Calling OpenVera Tasks from SystemC . . . . . . . . . . . . . . . . Calling SystemC from OpenVera . . . . . . . . . . . . . . . . . . . . . 3. Compiling and Running Testbenches Compiler Command Line Options . . . . . . . . . . . . . . . . . . . . . . . . . . General Options. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Compilation Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2 3-2 3-4 2-17 2-20 2-21 2-22 2-24 2-26 2-26 2-27 2-27 2-28 2-29 2-32 2-32

Running Vera with a Simulator . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-28 Runtime Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-28 On and Off Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-30 Options Requiring User-Specified Values . . . . . . . . . . . . . . . . . 3-35 Passing Data at Runtime. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-43 Referencing Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-45

iv

External Declaration of Subroutines . . . . . . . . . . . . . . . . . . . . . . . . 3-45 4. Vera-SystemC Transaction Level Interface Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SystemC Memory Example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SystemC Memory Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Interface Configuration File . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using Vera to Create the TLI Infrastructure . . . . . . . . . . . . . . . . Creating the Vera Testbench Program . . . . . . . . . . . . . . . . . . . . Create SystemC main Program . . . . . . . . . . . . . . . . . . . . . . . . . 4-2 4-3 4-3 4-5 4-7 4-8 4-9

Compile and Run . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-10 5. Randomization in Vera Random Stability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Seeding for Randomization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-2 5-7

Randomization: Hierarchical Seed Saving . . . . . . . . . . . . . . . . . . . 5-10 randcase Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-12 Random Number Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-14 random() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-14 urandom() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-15 rand48() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-16 urand48() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-16 urandom_range() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-17 random_range() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-18 rand_normal() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-18

rand_poisson() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-19 rand_t() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-19 rand_exponential() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-19 rand_erlang() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-20 rand_chi_square() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-20 Constraint Based Randomization . . . . . . . . . . . . . . . . . . . . . . . . . . 5-21 Random Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-27 Constraint Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . External Constraint Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Set Membership . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Distributions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Conditional Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hierarchical Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . Array Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Default Constraints. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Variable Ordering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Unidirectional Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . Function Calls in Constraints . . . . . . . . . . . . . . . . . . . . . . . . Static Constraint Blocks and Random Variables . . . . . . . . . 5-33 5-34 5-34 5-35 5-36 5-39 5-42 5-44 5-57 5-64 5-69 5-81 5-87

Randomize Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-88 Inline Constraints Using "randomize() with" . . . . . . . . . . . . 5-94 pre_randomize() and post_randomize() . . . . . . . . . . . . . . . . 5-96 Disabling Random Variables . . . . . . . . . . . . . . . . . . . . . . . . 5-98 Disabling Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-101 Dynamic Constraint Modification . . . . . . . . . . . . . . . . . . . . . . . . 5-103 Out of Body Declaration of Constraints . . . . . . . . . . . . . . . . . . . 5-104 Debugging Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-104

vi

Solver Choice. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-107 Automatic Solver Orchestration . . . . . . . . . . . . . . . . . . . . . . . . . 5-108 Internal Caching. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-109 Efficient Use of Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-110 Constraint Solver Diagnostics . . . . . . . . . . . . . . . . . . . . . . . . . . 5-111 Runtime Options. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-112 Control of Diagnostic Reporting . . . . . . . . . . . . . . . . . . . . . . 5-113 Solver Runtime Options to Control Memory and CPU Usage . 5-114 Compatibility with Vera Version 5.2 and older . . . . . . . . . . . . . . 5-115 Pre-6.0 Boundary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-118 Random Sequence Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-122 VSG Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-122 Production Declaration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-123 Production Controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-126 Weights for Randomization . . . . . . . . . . . . . . . . . . . . . . . . . 5-126 if-else Statements. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-127 case Statements. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-128 repeat Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-129 break Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-130 continue Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-131 Passing Values Between Productions . . . . . . . . . . . . . . . . . . . . 5-132 Value Declaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-132 Value Passing Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-133 6. Data Packing and Unpacking Pack and Unpack by System Functions . . . . . . . . . . . . . . . . . . . . . Pack and Unpack by Class Methods . . . . . . . . . . . . . . . . . . . . . . . . 6-2 6-3

vii

Identifying Data to Pack and Unpack . . . . . . . . . . . . . . . . . . . . . Packing Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Packing Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Unpacking Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Details of Pack and Unpack . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6-3 6-4 6-6 6-8 6-9

Pack and Unpack Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-10 7. Functional Coverage Coverage Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining Coverage Models Using Coverage Groups . . . . . . . . . . . Embedded Coverage Group . . . . . . . . . . . . . . . . . . . . . . . . . . . Instantiating Embedded Coverage Groups . . . . . . . . . . . . . 7-2 7-3 7-6 7-8

Class and Coverage Group Definitions in Different Files. . . . . . 7-12 Scoping Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-14 Additional Header File Needed to Access Sample Point . . . 7-14 Compiler reports mismatch between declaration and definition 7-18 Inheritance Does Not Override Coverage Groups . . . . . . . . 7-19 Multiple definitions of coverage groups is an error . . . . . . . . 7-19 External coverage definition is not possible in an aspect extension of a class. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-20 Vera Scoping Rules in Coverage Groups . . . . . . . . . . . . . . . . . 7-20 Defining Sampled Coverage Points . . . . . . . . . . . . . . . . . . . . . . Auto Bin Creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Overview of User Defined Bins for Coverage Points . . . . . . User-defined States for Coverage Points . . . . . . . . . . . . . . . 7-21 7-25 7-31 7-36

User-defined Illegal States for Coverage Points . . . . . . . . . . . . 7-42 User-defined Transitions for Coverage Points . . . . . . . . . . . 7-43

viii

User-defined Illegal Transitions for Samples . . . . . . . . . . . . 7-50 Cross Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-52 User-Defined Cross Coverage Bins . . . . . . . . . . . . . . . . . . . 7-56 Sample Event. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-63 Types of Sampling Events . . . . . . . . . . . . . . . . . . . . . . . . . . 7-63 Passing Arguments to Coverage Groups. . . . . . . . . . . . . . . . . . 7-70 Expressions within Coverage Group Definitions . . . . . . . . . . . . 7-75 Cumulative and Instance-based Coverage . . . . . . . . . . . . . . . . . . . 7-77 Cumulative Coverage. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-77 Instance-based Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-77 Measuring Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-78 Coverage Attributes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-80 Coverage Group Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-82 Unified Coverage Reporting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-86 Coverage Reporting Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-86 Coverage Data and Post-processing Tools . . . . . . . . . . . . . . . . . . 7-87 Unified Coverage Directory and Database Control . . . . . . . . . . 7-87 Loading Coverage Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-89 Instance Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-91 Predefined Coverage Group Tasks and Functions . . . . . . . . . . . . . 7-93 Activation/Deactivation: User Defined Bins . . . . . . . . . . . . . . . . . . 7-100 Coverage Feedback: query() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-106 Pre Vera X-2005.12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-115 Compile-Time Option: -covg_compat . . . . . . . . . . . . . . . . . . . . 7-115

ix

Auto-Bin Creation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-116 Cross Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-121 User-defined Cross Coverage Bins . . . . . . . . . . . . . . . . . . . 7-123 Enhancements to cross coverage . . . . . . . . . . . . . . . . . . . . . . . 7-130 Saving/reporting missing cross product bins . . . . . . . . . . . . 7-131 Disabling generation of automatic cross product bins . . . . . 7-134 Coverage Group Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-138 8. Reference Verification Methodology (RVM) 9. Temporal Assertions and Expressions Temporal Assertion Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Adding OVA Objects to a Testbench . . . . . . . . . . . . . . . . . . . . . Including the VeraOva.vrh Header File . . . . . . . . . . . . . . . . . . . Setting Up the OVAEngine Object . . . . . . . . . . . . . . . . . . . . . . . Controlling OVA Reporting. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Resetting OVA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setting Up the OVAAssert Objects . . . . . . . . . . . . . . . . . . . . . . Instantiating OVAAssert Objects . . . . . . . . . . . . . . . . . . . . . . . . Controlling Evaluation Attempts. . . . . . . . . . . . . . . . . . . . . . . . . Counting Successes and Failures . . . . . . . . . . . . . . . . . . . . . . . Setting Up the OVAEvent Objects . . . . . . . . . . . . . . . . . . . . . . . 9-4 9-4 9-4 9-5 9-5 9-6 9-6 9-6 9-8 9-9 9-9

Instantiating OVAEvent Objects . . . . . . . . . . . . . . . . . . . . . . . . . 9-10 Suspending Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-10 Eliminating OVAEvent Objects . . . . . . . . . . . . . . . . . . . . . . . . . . 9-11 Terminating the OVAEngine . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-11 Example Testbench . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-11

Compiling and Simulating OVA Objects. . . . . . . . . . . . . . . . . . . 9-13 Running a Vera Simulation with OVA . . . . . . . . . . . . . . . . . . . . . . . 9-13 Getting Started. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-14 The OVAsim Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-14 -ova option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-16 New Vera-OVASIM Flow with Different Simulators . . . . . . . . . . 9-16 Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-18 Task Invocation from the Simulators Prompt . . . . . . . . . . . . . . . 9-18 Viewing Results with the Report File . . . . . . . . . . . . . . . . . . . . . 9-19 Using OVA Assertions with Vera and Third Party Simulators . . . . . 9-20 Compiling and Simulating with VCS . . . . . . . . . . . . . . . . . . . . . 9-20 Vera and VCS MX simulation Verilog top . . . . . . . . . . . . . . . 9-20 Vera and VCS MX simulation . . . . . . . . . . . . . . . . . . . . . . . . 9-21 Compiling and Simulating with NC-Verilog . . . . . . . . . . . . . . . . 9-22 Compiling and Simulating with NC-VHDL . . . . . . . . . . . . . . . . . 9-23 Compiling and Simulating with MTI Verilog . . . . . . . . . . . . . . . . 9-24 Compiling and Simulating with MTI VHDL . . . . . . . . . . . . . . . . . 9-25 10. Testbench Optimization Vera Performance Profiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2 Profiling Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2 Performance Profiler Example . . . . . . . . . . . . . . . . . . . . . . . . . . 10-4 Vera Memory Profiler. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-7 Profiling Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-8 Profiled Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-10 Memory Profiler Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-12

xi

Memory Profiling Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-15 Using vera_profile_object_verbose . . . . . . . . . . . . . . . . . . . 10-15 Verbose Profile Example . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-16 Save and Restart. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-19 Linking Vera with VCSs Save/Restart . . . . . . . . . . . . . . . . . . . . 10-19 Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-21 Dynamic Loading of Vera Object Files . . . . . . . . . . . . . . . . . . . . . . 10-24 Creating a Vera Dynamic Executable Object (VDEO) . . . . . . . . 10-24 Loading and Unloading a VDEO File . . . . . . . . . . . . . . . . . . . . . 10-26 Loading. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-26 Unloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-27 Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-28 Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-29 11. Vera Interactive Debugger Debugger Overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-3 How Debugging Works . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-6 Menus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-8 Toolbar Buttons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-13 Project Workspace Window. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-13 Source Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-20 Local Watch Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-22 Global Watch Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-24 Debugging with Breakpoints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-26

xii

Stepping Vera Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-31 Watching Variables and Expressions . . . . . . . . . . . . . . . . . . . . . . . 11-32 Forcing a Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-33 Finding a String in Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-34 Preferences and Fonts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-36 Debugger Settings File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-39 Displaying the simulation log file . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-40 Enabling the LogWindow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-40 12. Vera Waveform Interface OpenVera Plot Declaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-2 vera_plot() Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-5 vera_plot() Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-7 Supported Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-7 OpenVera Plot Control. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-9 Plotting for VirSim Waveform Tool . . . . . . . . . . . . . . . . . . . . . . . . . . 12-9 Post Simulation Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-10 Interactive Simulation Mode. . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-10 Plotting for MTI-ModelSim Waveform Tool . . . . . . . . . . . . . . . . . . . 12-11 Post Simulation Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-12 Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-13 Plotting for Novas-Debussy Waveform Tool. . . . . . . . . . . . . . . . . . . 12-14 Post Simulation Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-15 Interactive Simulation Mode. . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-16

xiii

Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-17 13. Project-Based Testbenches Vera Project File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-2 Vera Configuration File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-3 Timescale Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-3 Clock Statement. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-5 Clock Port. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-5 Clock Alias Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-6 Connect Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-6 Veritask Statement. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-9 Template for Vera Configuration File . . . . . . . . . . . . . . . . . . . . . 13-10 Vera Object Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-11 Project-based Configuration Simulation . . . . . . . . . . . . . . . . . . . . . 13-11 Main-Specific Plus Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . 13-13 Instance-Specific Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-14 Mixed HDL Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-15 14. Testbenches for Verification Intellectual Property Verification IP Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-2 Creating VIP Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-2 Protected VIP Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-3 Setting Up a VIP Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-3 Installing the VIP Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-4 Typical VIP Contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-5

xiv

Generated Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-7 Header Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-7 Documentation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-8 Writing a VIP Testbench . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-8 Editing the Makefile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-10 Configuring the VIP Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-11 Automated Loading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-11 Passing Properties via HDL Parameters . . . . . . . . . . . . . . . 14-14 C and HDL Testbenches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-15 VIP Implementation Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-15 C Testbenches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-16 HDL Testbenches. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-17 Command Interfaces for C and HDL Testbenches . . . . . . . . 14-18 Mixed Vera Testbenches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-20 Creating Verification IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-22 Connection to the Users Testbench . . . . . . . . . . . . . . . . . . . . . 14-22 File Naming Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-25 Developing a VIP Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-25 Avoiding Naming Conflicts . . . . . . . . . . . . . . . . . . . . . . . . . . 14-26 Connecting to HDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-27 Automatic Object Loading . . . . . . . . . . . . . . . . . . . . . . . . . . 14-27 Including Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-29 Preventing Multiple Inclusion . . . . . . . . . . . . . . . . . . . . . . . . 14-29 VIP File Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-30 Deliverable Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-30 VIP Coding Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-31

xv

Naming Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-31 Header File Naming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-32 Version Checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-32 Classes and Coverage Object Declarations. . . . . . . . . . . . . 14-34 Multiple Instance Support. . . . . . . . . . . . . . . . . . . . . . . . . . . 14-35 Index

xvi

Preface
This preface includes the following sections: About This Guide Customer Support

FIX ME!

xvii

Known Limitations and Resolved STARs


Information about known problems and limitations, as well as about resolved Synopsys Technical Action Requests (STARs), is available in the Vera Release Note in SolvNET. To see the Vera Release Notes, 1. Go to the Synopsys Web page at http://www.synopsys.com and click SolvNet. 2. If prompted, enter your user name and password. If you do not have a SolvNet user name and password, you can obtain them at http://www.synopsys.com/registration. 3. Click Release Notes in the Main Navigation section (on the left), click Vera, then click the release you want in hte list that appears at the bottom. The Vera Release Notes are available through the Vera Document Navigator.

About This Guide


The Vera User Guide introduces you to Vera, an advanced testbench automation solution. This guide covers basic Vera tool operation and testbench design topics. The OpenVera LRM: Testbench and Reference Verification Methodology User Guide documents address, in more detail, the OpenVera hardware verification language and the Reference Verification Methodology, respectively. This guide serves as a supplemental teaching guide as well as a reference for the user.

xviii

Audience
This book is intended to be used by engineers experienced with either Verilog or VHDL. Because OpenVera is used to create programs that link with Verilog and/or VHDL hardware designs, you should have a fundamental understanding of the hardware description language used in the design. This book assumes basic knowledge of hardware design verification. For assumptions about hardware and software environment go to http://www.synopsys.com/products/sw_platform.html

Related Publications
For additional information about Vera see Synopsys Online Documentation (SOLD), which is included with the software release. Documentation on the Web, which is available through SolvNet at http://solvnet.synopsys.com. The Synopsys Print Shop, from which you can order printed copies of Synopsys documents, at http://docs.synopsys.com. The Vera Configuration Guide is available through the Vera Document Navigator.

You might also want to refer to the documentation for the following related Synopsys products: VCS DesignWare Library

xix

FlexModel VirSim

xx

Conventions
The following conventions are used in Synopsys documentation.
Convention Description

Courier

Indicates command syntax. Indicates a user-defined value in Synopsys syntax, such as object_name. (A user-defined value that is not Synopsys syntax, such as a user-defined value in a Verilog or VHDL statement, is indicated by regular text font italic.) Indicates user inputtext you type verbatim in Synopsys syntax and examples. (User input that is not Synopsys syntax, such as a user name or password you enter in a GUI, is indicated by regular text font bold.) Denotes optional parameters, such as
pin1 [pin2 ... pinN]

Courier italic

Courier bold

[]

Indicates a choice among alternatives, such as


low | medium | high

(This example indicates that you can enter one of three possible values for an option: low, medium, or high.) _ Connects terms that are read as a single term by the system, such as
set_annotated_delay

Control-c

Indicates a keyboard combination, such as holding down the Control key and pressing c. Indicates a continuation of a command line. Indicates levels of directory structure. Indicates a path to a menu command, such as opening the Edit menu and choosing Copy.

\ / Edit > Copy

xxi

Customer Support
Customer support is available through SolvNet and through contacting Vera Support.

Accessing SolvNet
SolvNet is the Synopsys electronic knowledge base, which contains information about Synopsys and its tools and is updated daily. To access SolvNet, 1. Go to the SolvNET Web page at http://solvnet.synopsys.com. 2. If prompted, enter your user name and password. If you do not have a SolvNet user name and password, you can obtain them at http://www.synopsys.com/registration. If you need help using SolvNet, click SolvNet Help in the column on the left side of the SolvNet Web page.

Contacting Vera Support


If you have problems, questions, or suggestions, you can contact Vera Support in the following ways: Send an e-mail message to vera-support@synopsys.com.

xxii

Telephone the Synopsys Technical Support Center. - Call (800) 245-8005 from within the continental United States. - Call (650) 584-4200 from Canada.

Open a call to your local support center from the Web by going to http://solvnet.synopsys.com (SolvNet user name and password required), then clicking Enter a Call.

xxiii

xxiv

1
Introduction 1
Vera is an integral part of the Synopsys Smart Verification platform. It is the comprehensive testbench automation solution for module, block and full system verification. The Vera testbench automation system is based on the OpenVera language. This is an intuitive, high-level, object-oriented programming language developed specifically to meet the unique requirements of functional verification. With Vera, it is easy to quickly model the target environment at a high level of abstraction while automatically generating constrained random stimulus. Veras Constraint Solver Engine is used to automatically generate tests that mimic "real-life" stimuli with the application of the verification engineers constraints. Constrained random stimulus enables the detection of a wide range of bugs including functional and corner cases. These self-checking tests written in OpenVera eliminate the need to analyze manually

1-1

simulation waveforms and reports. Its built-in dynamic coverage analysis provides instant coverage feedback, facilitating the efficient generation of high coverage stimuli. Key benefits of Vera are: It enables the generation of high coverage, constraints-driven random stimulus generation It enables scalable and re-usable testbenches with OpenVera the open source Hardware Verification Language It leverages testbenches across all HDLs including VHDL, Verilog, and SystemC It improves simulation efficiency with intelligent, reactive test generation It increases simulation through the usage of distributed processing It accelerates verification ramp up with a large offering of OpenVera Verification IP It leverages high performance, OpenVera assertions, temporal assertion technology to accelerate the development of monitors and checkers

Introduction 1-2

Overview of Testbench Development


Architectural and block-level specifications capture the intended functionality of a design. These are the standards that designers rely on to implement as a product. In parallel with the design effort, a verification plan is created. This document prioritizes the various features (whether visible to the end user or not) that need to be tested as the design evolves from specification to implementation. The relative priority of these tests is established in the verification plan, as is the schedule for developing the infrastructure and actual tests for each. The product is typically partitioned hierarchically at several levels; as a system, as a chip, and as constituent functional blocks. Each level of abstraction has a segment of the verification plan dedicated to it. The testbench infrastructure should incorporate self-checking to ease maintainability and ensure the highest degree of automation possible. Each feature test will then report its pass/fail status, which can be aggregated into a snapshot of the design at any time. Self-checking may be implemented by comparing the observed outputs with the expected ones (from a reference model) or via a loopback mechanism. In addition to self-checking, constrained random stimulus generation, along with functional coverage monitoring to calibrate the degree to which the enumerated points in the functional space, as documented in the verification plan, have been tested, completes the picture for a state-of-the art verification methodology. Implementing this using Vera greatly increases the confidence of the project team that the product will work the first time it is fabricated, packaged, and delivered.

Introduction 1-3

Components of a Basic Vera Verification Environment


A basic Vera verification environment includes a Vera testbench, a Vera shell file, an HDL design (Device Under Test, or DUT), and a top level HDL file that includes the DUT, the Vera shell file, and a clock generator (see Figure 1-1). Figure 1-1 Components of a Basic Vera Verification Environment Top Level HDL file DUT Vera shell
Vera Testbench
interface

clock
input clk SystemClock

input clk CLOCK

clock generator

A Vera testbench is a collection of Vera files created to verify a DUT. The OpenVera program construct and at least one OpenVera interface declaration must be included in the testbench. An OpenVera interface declaration specifies a set of signals to be connected to the HDL domain, and a clock signal that controls the driving and sampling of the interface signals. The interface declaration can either be saved as a header file (.vrh) to be included in a Vera file (.vr), or declared in the .vr file itself. The recommended naming convention for an interface declaration file is filename.if.vrh.

Introduction 1-4

Example 1-1 shows an example of an OpenVera interface declaration for a 2-bit round-robin arbiter design, rrarb.if.vrh: Example 1-1 OpenVera Interface Declaration
interface rrarb { input clk CLOCK ; input [1:0] grant PSAMPLE #-1 ; output [1:0] request PHOLD #1 ; output reset PHOLD #1 ; }

The interface declaration shown in Example 1-1 defines three interface signals (grant[1:0], request[1:0], and reset) that are synchronized to the positive edge of the interface clock, clk. Directions of the interface signals are defined from the perspective of a Vera testbench. Vera samples input interface signals and drives output interface signals. Signal skews are specified (-1 for input and 1 for output) to prevent potential race conditions. Example 1-2 shows a basic Vera testbench for a 2-bit round-robin arbiter design. Example 1-2 Basic Vera Testbench
rrarb.vr #include <vera_defines.vrh>// include Vera pre-defined header file #include "rrarb.if.vrh"// include interface file program rrarb_test { // reset rrarb.request = 2'b00; rrarb.reset = 1; @1 rrarb.reset = 0; // single request @1 rrarb.request[0] = 1'b1;// drive request @2 rrarb.grant == 2'b01;// sample grant printf("Request from device 0:\tgrant = %b\n", rrarb.grant); @1 rrarb.request[0] = 1'b0;// release request rrarb.request[1] = 1'b1;

Introduction 1-5

@2 rrarb.grant == 2'b10 ; printf("Request from device 1:\tgrant = %b\n", rrarb.grant); rrarb.request[1] = 1'b0 ; // round-robin test @1 rrarb.request[0] = 1'b1 ; rrarb.request[1] = 1'b1 ; @2 rrarb.grant == 2'b01 ;// should get grant 0, since last //request was 1 printf("Requests from device 0 and device 1:\tgrant = %b\n", rrarb.grant); @1 rrarb.grant == 2'b10 ; // keep asserting both ports, should // get grant 1 printf("Requests from device 0 and device 1:\tgrant = %b\n", rrarb.grant); rrarb.request[0] = 1'b0 ; rrarb.request[1] = 1'b0 ; } // end of program rrarb_test

The testbench drives the request[1:0] signal, then it samples the grant[1:0] signal and checks for the expected values. After the compilation of a Vera file containing the OpenVera program construct, a Vera shell file is generated. The shell file is an HDL file with port declarations that map to the OpenVera interface declarations in the Vera testbench, and an additional input port, SystemClock. Simulator specific interface calls are included in this shell file. Any modification to the Vera shell file is strongly discouraged. Shell files generated for each supported Verilog simulator are the same. Whereas, shell files generated for VHDL simulators vary. In a top level HDL file, the shell file is instantiated and ports of the instantiated shell file are connected to the desired HDL signals.

Introduction 1-6

SystemClock
SystemClock is a Vera internal reference signal used only for the OpenVera system function, get_cycle(), and when using the keyword, CLOCK. Connecting SystemClock to the master clock of a verification environment is recommended. SystemClock can be left unconnected if the get_cycle() function or CLOCK keyword is not used.

The Template Generator


The Vera Template Generator provides you with an easy way of creating a set of basic template files for testbench creation. You can then edit these files to suit your needs. The template generator reads in a DUT file and creates a Vera interface declaration file (.if.vrh), a Vera file template (.vr.tmp), and a top level HDL file template (.v, or .vhd). These generated template files provide the framework for coding. Note: The input DUT file for the template generator should contain only valid VHDL or Verilog code. Verilog users should remember that the HDL module name cannot start with a digit (for example, 2mod is not permitted). Ports declared within module declarations, a Verilog 2001 standard, can be used to parse port attributes, such as direction, width, net_type, etc. These are embedded within the module declaration to the template generator.

Introduction 1-7

Three styles of Verilog 2001 standard port declaration are currently allowed, they are:
module top (input [3:0] IN1,IN2, output [3:0] OUT1); module top(input wire [3:0] IN1, output reg signed [3:0] OUT1,OUT2); module top (IN1,IN2,OUT1); input wire [3:0] IN1,IN1; output reg signed [3:0] OUT1; ..... .... endmodule

The template generator does not support parameter declarations inside module declarations. To invoke the template generator, enter the following command:
vera -tem template_options HDL_filename

template_options: These can ne one or more of the following options:


Option Definition Required

-I -c -t | -vhdl_t

Includes the directory in the search path Specifies the DUT clock signal Specifies the Verilog | VHDL module name

no no yes

-I path_name This adds an absolute or relative path to the search path for include files.

Introduction 1-8

-c clock_signal This specifies the clock signal on the HDL module, where clock_signal is the DUT signal to be connected to SystemClock. SystemClock is a clock generated by Vera. When specified, the defined (DUT) clock signal is connected to SystemClock and is identified as CLOCK in the interface specification. If omitted, SystemClock is used as the sampling clock. -t | -vhdl_t module_name and HDL_filename This specifies the top HDL module name. The -t or -vhdl_t option is mandatory. where: - module_name is the name of the top HDL module from which the template is being generated. - HDL_filename is the HDL file from which the template is generated. - The file HDL_filename is either a Verilog (.v file) or a VHDL (.vhd file) containing the top level module instantiated within the test_top.v or test_top.vhd file. For example: VHDL:
% vera -tem -vhdl_t rrarb -c clk rrarb.vhd

Here rrarb is the module name, and clk is the clock signal name in the DUT file, rrarb.vhd. Verilog:
% vera -tem -t rrarb -c clk rrarb.v

Introduction 1-9

Here rrarb is the module name, and clk is the clock signal name in the DUT file, rrarb.v.

Vera Interactive Debugger


The Vera graphical debugger is a valuable debugging and testbench analysis tool. Its windowed interface allows easy configurability, simplifying use. Its monitoring mechanisms grant access to variables, signals, and expressions resulting in quick and simple testbench analysis. Details of the debugger are documented in Chapter 11, Vera Interactive Debugger.

Running Vera Standalone


The Vera cycle-based simulator (vera_cs) can run Vera models stand-alone or linked with additional C models. This simulator is useful for rapid prototyping of a Vera testbench or behavioral model while waiting for the HDL DUT to be ready. It is also very useful for trying out small examples when learning Vera. To use the stand-alone simulator, compile the Vera files and then use the following command line to run the simulation:
% vera_cs filename.vro

Note: All drives in vera_cs are ignored, and all samples are received as Xs.

Introduction 1-10

2
Using Vera 2
A Vera testbench can drive the design under test (DUT) effectively for verification, abstracting the stimulus generation-response checking mechanism for productivity. The DUT can be written in one or more of the existing Hardware Design Languages currently available: Verilog, VHDL, or SystemC. This chapter details the mechanisms through which the DUT is wired to the testbench so that the testbench can drive its inputs and observe its outputs.

Using Vera 2-1

The Vera Testbench Flow


There are numerous ways to construct a Vera testbench. This section outlines a simple flow for Verilog and VHDL-based designs. The Vera template generator is used here to start the process. Figure 2-1 illustrates the components of the Vera testbench. Figure 2-1 Template Generator and Components of a Vera Testbench Testbench top_level file DUT instance Vera Shell File interface

filename.if.vrh
filname.v filename_shell.v or filename_shell.vhd

Vera Program
Template filename.vr.tmp

~
Verilog-based Flow VHDL-based Flow

clock generator

Using Vera 2-2

Verilog-based Flow
The procedure for creating a Vera testbench for Verilog-based designs is as follows: 1. The first step is to invoke the template generator:
vera -tem -t module_name -c clock filename.v

2. Rename the template Vera program file from filename.vr.tmp to filename.vr. 3. Add code to the Vera program file (filename.vr). 4. Compile the Vera program file:
vera -cmp -vlog filename.vr

This creates two files: a. an object code file .vro file b. a filename_shell.v file, which corresponds to the Vera Shell File component of the top_level depicted in Figure 2-1. The Vera filename.shell.v file acts as the interface between the Vera program and the DUT. Do not edit this file. Note: Using the -vlog switch results in the creation of a Vera shell file named filename_shell.v. If this switch is not used, the compiler will assume that the source is Verilog and will create a Vera shell file named filename.vshell. 5. Create the simv executable:
vcs -vera filename.v filename_shell.v \ filename.test_top.v

Using Vera 2-3

6. Run the simulation:


simv +vera_load=filename.vro

Note: The command line here is appropriate for VCS on Solaris. For other Verilog simulators, see the Vera Configuration Guide in:
$VERA_HOME/doc/config.pdf

After successful simulation, you will see a simulation execution report something like the following:
Vera: finish encountered at time 11350 cycle 114 total mismatch: 1 vca_error: 0 fail(expected): 0 drive: 2 force: 1 expect: 1 sample: 4 sync: 102 VCS Simulation Report Time: ___ CPU Time: ___ Data Structure size: __ Date

The information in each line is as follows: total mismatch: Is a counter for all expect failures in which soft is not used. For example, for each failure of the following line:
@0 counter.cnt == 8h05;

The mismatch is incremented vca_error: Covers all the VCA errors, as described in the OpenVera LRM: Testbench document.

Using Vera 2-4

fail (expected): Counts the failures you expect. All soft expects which result in failures are counted here. Note, if soft is used for an expect which is bound to fail, then fail (expected) will increment, and not mismatch. If you omit soft, then mismatch will increment. drive: The number of variable assignments to output signals from Vera. expect: The number of times an expect statement was executed regardless of the result. This count is incremented for the following successful expect:
@0 counter.cnt == 8h04; //This is the correct expect. ###########END PROGRAM Vera: finish encounter at time 11350 cycle 114 total mismatch: 0 vca_error: 0 fail(expected): 0 drive: 2 expect: 1 sample: 4 sync: 102

sample: The number of times an input signal is sampled and assigned to a variable or signal. sync: The number of times Vera is explicitly synchronized to a clock. For example, each of these statements will increment the count by 1:
@(posedge CLOCK); @(posedge a.clk);

Using Vera 2-5

exit_status If the Vera program has exited with non-zero status (usually an indication of an error), exit_status will appear. For example:
exit_status: 33

This is the value of the argument passed to Veras predefined exit() task. Do not rely on the value of the simulators exit status to determine if the Vera program terminated normally. The simulators exit status may or may not reflect the exit status of Vera.

VCS Example
This example starts with the following design under test (an adder):
module adder(in0, in1, out0, clk); input[7:0] in0, in1; input clk; output[8:0] out0; reg[8:0] out0; always@(posedge clk) begin out0 <= in0 + in1; end endmodule

1. The first step is to invoke the template generator:


vera -tem -t adder -c clk adder.v

which creates the following files: a. The interface file (adder.if.vrh):


// adder.if.vrh #ifndef INC_ADDER_IF_VRH #define INC_ADDER_IF_VRH

Using Vera 2-6

interface adder{ output [7:0] in0 OUTPUT_EDGE OUTPUT_SKEW; output [7:0] in1 OUTPUT_EDGE OUTPUT_SKEW; input [8:0] out0 INPUT_EDGE #-1; input clk CLOCK; } //end of interface adder #endif

b. The test_top file (adder.test_top.v):


module adder_test_top; //adder.test_top.v parameter simulation_cycle = 100; reg SystemClock; wire [7:0] in0; wire [7:0] in1; wire [8:0] out0; assign clk = SystemClock; vera_shell vshell( //Vera shell file .SystemClock(SystemClock), .adder_in0 (in0), .adder_in1 (in1), .adder_out0 (out0), .adder_clk (clk), ); ifdef emu /*DUT is in emulator, so not instantiated here*/ else adder dut( .in0 (in0), .in1 (in1), .out0 (out0), .clk (clk), ); endif initial begin //clock generator SystemClock = 0; forever begin #(simulation_cycle/2) SystemClock = ~SystemClock; end end endmodule

Using Vera 2-7

c. The Vera file (adder.vr), which is copied from the Vera template file (adder.v.tmp):
// adder.vr (copied from the template adder.v.tmp) #define OUTPUT_EDGE PHOLD #define OUTPUT_SKEW #1 #define INPUT_EDGE PSAMPLE #include <vera_defines.vrh> // define any interfaces, and verilog_node here #include "adder.if.vrh" // // // // define any ports, binds here declare any external tasks/classes/functions here declare any hdl_task(s) here declare any class typdefs here

program adder_test { // start of top block // define any global variables here // Start of adder_test // Type your test program here: // Example of drive: // @ 1 adder.in0 = 0; // Example of expect: // @ 1,100 adder.out0==0; // Example of what you are to add: @ (posedge adder.clk); // line up to first clock @0 adder.in0=8hff; // drive "ff" to the design @2 adder.out0 == 9h1fe; // expect "1fe" from the design } // end of program adder_test // define any tasks/classes/functions here

Using Vera 2-8

d. The Vera shell file (adder_shell.v; do not edit this file):


// adder_shell.v module vera_shell( SystemClock, adder_in0, adder_in1, adder_out0, adder_clk ); input SystemClock; output [7:0] adder_in0; output [7:0] adder_in1; input [8:0] adder_out0; inout adder_clk; //Nest which VMC will reference // System clock:SystemClock wire SystemClock; // Other components of this file are not listed here ... endmodule

2. The next step is to compile the adder.vr file, which creates the adder_shell.v and adder.vro files:
% vera -cmp -vlog adder.vr

3. Now you can create the simv executable:


% vcs -vera adder.v adder_shell.v adder.test_top.v

4. And finally, you can run the simulation:


% simv +vera_load=adder.vro

Figure 2-2 summarizes the testbench setup flow using the Template Generator.

Using Vera 2-9

Figure 2-2 Testbench Flow using the Template Generator


Verilog Source adder.v

Generate Template
vera -tem -t adder -c clock adder.v

Test Top File Test File


adder.test_top.v

Temporary File Temporary File


adder.vr.tmp

Interface HeaderFile Interface Header File


adder.if.vrh

Rename & Edit

Vera Template
adder.vr

Vera Compile
vera -cmp -g adder.vr

Verilog Interface Shell adder.vshell

Vera Object File adder.vro

VCS Compile
vcs -vera adder.v adder.test_top.v adder.vshell

Run Simulation
simv +vera_load=adder.vro

Using Vera 2-10

VHDL-based Flow
The procedure for creating a Vera testbench for VHDL-based designs is as follows: 1. The first step is to invoke the template generator:
$vera -tem -vhdl_t top_entity [-c clk] filename.vhd

top_entity Defines the name of the top entity. filename Is the VHDL design The vhdl_t option reads the top module name. Invoking the template generator results in three files being generated: - An interface file: filename.if.vrh - A top-level file: filename_top.vhd - A skeletal Vera program file: filename.vr.tmp 2. Edit the interface (.if.vrh) file: The signal width for any user-defined types has to be specified. 3. Rename the template Vera program file from filename.vr.tmp to filename.vr. 4. #include filename.if.vrh and add code to the Vera program file (filename.vr). 5. Compile the Vera program file:
vera -cmp -simulator filename.vr

Using Vera 2-11

This creates two files: - an object code file .vro file - a filename_shell.vhd file The Vera filename_shell.vhd file acts as the interface between the Vera program and the DUT. Do not edit this file. 6. Run the simulation:
echo "vera_load = filename.vro" > vera.ini

VHDL Example
//alu.vhd library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity alu_ent is port ( rst : in std_logic; clk : in std_logic; op : in std_logic_vector(1 downto 0); inp1 : in std_logic_vector(7 downto 0); inp2 : in std_logic_vector(7 downto 0); outp : out std_logic_vector(7 downto 0) ); end; architecture alu_arch of alu_ent is signal outp2 : std_logic_vector(15 downto 0); begin proc1 : process(clk) begin if (clk'event and clk = '1') then if (rst = '1') then outp <= (others=>'0');

Using Vera 2-12

else case op is when "00" => outp <= inp1 + inp2; when "01" => outp <= inp1 - inp2; when "10" => outp2 <= inp1 * inp2; outp <= outp2(15 downto 8); when "11" => -- outp <= inp1 / inp2; outp <= (others=>'0'); when others => null; end case; end if; end if; end process proc1; end;

1. The first step is to invoke the template generator:


vera -temp -vhdl_t alu_ent -c clk alu.vhd

which creates the following files: a. The interface file (alu_ent.if.vrh):


#ifndef _INTERFACE_ALU_ENT_ #define _INTERFACE_ALU_ENT_ #define #define #define #define OUTPUT_EDGE PHOLD OUTPUT_SKEW #1 INPUT_SKEW #-1 INPUT_EDGE PSAMPLE

vera_shell_param vera_vhdl_temp_ieee = "ieee::std_logic_unsigned:std_logic_1164:"; /* * User may modify the interface to add additional signals * or paths to hdl_node(s) */

Using Vera 2-13

interface alu_ent { input [7:0] outp INPUT_EDGE INPUT_SKEW hdl_node "{STD_LOGIC}"; output [7:0] inp2 OUTPUT_EDGE OUTPUT_SKEW hdl_node "{STD_LOGIC}"; output [7:0] inp1 OUTPUT_EDGE OUTPUT_SKEW hdl_node "{STD_LOGIC}"; output [1:0] op OUTPUT_EDGE OUTPUT_SKEW hdl_node "{STD_LOGIC}"; input clk CLOCK; output rst OUTPUT_EDGE OUTPUT_SKEW hdl_node "{STD_LOGIC}"; } // end of interface alu_ent #endif

b. The test_top file (alu_ent_top.vhd):


library IEEE; use IEEE.std_logic_unsigned.all; use IEEE.std_logic_1164.all; use WORK.vera_shell_pkg.all; ENTITY dut_bench IS END; ARCHITECTURE dut_bench_arch OF dut_bench IS SIGNAL system_clock : std_logic := '0'; SIGNAL alu_ent_outp : std_logic_vector(7 downto 0); SIGNAL alu_ent_inp2 : std_logic_vector(7 downto 0); SIGNAL alu_ent_inp1 : std_logic_vector(7 downto 0); SIGNAL alu_ent_op : std_logic_vector(1 downto 0); SIGNAL alu_ent_clk : std_logic := '0'; SIGNAL alu_ent_rst : std_logic; COMPONENT alu_ent PORT ( SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL ); END COMPONENT;

outp : OUT std_logic_vector(7 downto 0); inp2 : IN std_logic_vector(7 downto 0); inp1 : IN std_logic_vector(7 downto 0); op : IN std_logic_vector(1 downto 0); clk : IN std_logic; rst : IN std_logic

BEGIN system_clock <= not system_clock after 50 ns; alu_ent_clk <= not alu_ent_clk after 50 ns; vera_shell_inst : vera_shell PORT MAP(

Using Vera 2-14

SystemClock => system_clock, alu_ent_outp => alu_ent_outp, alu_ent_inp2 => alu_ent_inp2, alu_ent_inp1 => alu_ent_inp1, alu_ent_op => alu_ent_op, alu_ent_clk => alu_ent_clk, alu_ent_rst => alu_ent_rst ); dut_inst : alu_ent PORT MAP( outp => alu_ent_outp, inp2 => alu_ent_inp2, inp1 => alu_ent_inp1, op => alu_ent_op, clk => alu_ent_clk, rst => alu_ent_rst ); END

c. The Vera file (alu.vr), which is copied from the Vera template file alu_ent.vr.tmp):
#include <vera_defines.vrh> // define interfaces, and vhdl_node here if necessary #include "alu_ent.if.vrh" // define ports, binds here if necessary // declare external tasks/classes/functions here if necessary // declare hdl_tasks here if necessary // declare class typedefs here if necessary program alu_ent_test { // start of top block // define global variables here if necessary // Start of alu_ent_test // Type your test program here: // // Example of drive:

Using Vera 2-15

// @1 alu_ent.outp = 0 ; // // // Example of expect: // @1,100 alu_ent.inp2 == 0 ; // } // end of program alu_ent_test

// define tasks/classes/functions here if necessary

2. The next step is to compile the alu.vr file, which creates the alu_shell.v and alu.vro files:
% vera -cmp -simulator alu.vr

3. And finally, you can run the simulation:


echo "vera_load = alu.vro" > vera.ini

Simulator Specific Instructions Compiling and Simulating with MTI-Vhdl 1. vlib work 2. vsim c dut_bench do run all; quit 3. vmap work work 4. vcom filename.vhd filename_shell.vhd filename_top.vhd 5. vsim c dut_bench do run all; quit Compiling and Simulating with VCS-MX 1. vhdlan nc event filename.vhd filename_shell.vhd filename_top.vhd 2. scsim nc dut_bench

Using Vera 2-16

Compiling and Simulating with NC-VHDL 1. mkdir work 2. ncvhdl mefilename.vhd filename_shell.vhd filename_top.vhd 3. ncelab me access +rwc work.dut_bench:dut_bench_arch 4. ncsim me work.dut_bench:dut_bench_arch

Mixed HDL-based Flow


A mixed design is defined as a design in which a Verilog module instantiates a VHDL module or vice-versa. That is, the design can be either a Verilog top, or VHDL top design. Vera supports three mixed design simulators: VCS-MX, ModelSim SE and NC-Sim. The following features are supported. Sampling and driving a statically bound Verilog/VHDL signal residing in any layer of the mixed design. Importing a task defined in the top Verilog or inside a VHDL package. Dynamically connecting (binding) a Vera signal to a Verilog/ VHDL signal (through signal_connect()), then driving or sampling the signal. Slices of the vectors can be connected to. The signal can be in any layer of the mixed design.

Using Vera 2-17

Sampling and driving a statically connected signal To statically connect a Vera signal to an intermediate node (that is, a non-port signal in the DUT, which may or may not be a mixed signal), use the keyword hdl_node when specifying the signal connections inside the interface. Consider the following design: 1. Verilog modules
module top(a, b, c); // the top module ...... ...... reg d; ...... vh_inst vh_mod(a, d); // Instantiating a VHDL module vl_inst vl_mod(b, c); // Instantiating a Verilog module ...... endmodule module vl_mod(ip, op); ...... reg local; ...... endmodule

2. VHDL module
entity vh_mod is port (sig1 : IN std_logic; sig2 : OUT std_logic); ...... architecture arch of vh_mod is ...... signal local: std_logic; ...... end arch;

Using Vera 2-18

3. Vera Testbench Assume the top module is instantiated inside the test_top file as dut. The Vera testbench can then access the intermediate nodes like dut.vh_inst.local or dut.vl_inst.local or dut.vh_inst.sig1. These signals are accessed in the same way as any intermediate node in other simulators.
interface intf_a { ...... output vh_local PHOLD #1 hdl_node "dut.vh_inst.local"; input vl_local PSAMPLE hdl_node "dut.vl_inst.local" ; output vh_port PHOLD #1 hdl_node "dut.vh_inst.sig1" ; ...... }

Importing a Verilog/VHDL task 1. Place all the VHDL tasks in a separate package. Note that only those VHDL tasks which are defined in a package can be imported and only those Verilog tasks which are defined in the top layer Verilog modules can be imported. 2. Inside the Vera testbench, use the keyword hdl_task to declare all the tasks you want to import. 3. Insert the keywords verilog_task or vhdl_task, as appropriate, enclosed within braces inside the task path.
........ hdl_task veri_task_imported()"{verilog_task}top.top_veri_task"; hdl_task vhdl_task_imported() "{vhdl_task}work.vhdl_task_pkg.proc0"; hdl_task arg_vh_task_imported(var int a) "{vhdl_task}work.vhdl_task_pkg.proc1"; ........ // The default hdl_task type is verilog_task. ...

Using Vera 2-19

// Vera Program starts program import_task_test() { int b=10; ... veri_task_imported(); vhdl_task_imported(); ... arg_vh_task_imported(b); ... }

Sampling and driving a dynamically connected signal Use the signal_connect() system function in the same way as with other simulators.

Use Models with Different Simulators


From Vera version 6.4 onwards, there are two use models for VCS-MX: 1. The flow where two switches, -vcs_mx and -sro_mx are used for Verilog-top and VHDL-top designs, respectively. 2. The new simplified use model where a single switch, -mx is used for both Verilog-top and VHDL-top designs. These use models are described in the following sections, VCS-MX (Verilog on top) on page 2-21, VCS-MX (VHDL on top) on page 2-22, and Simplified Use Model for VCS-MX on page 2-24

Using Vera 2-20

VCS-MX (Verilog on top)


1. Compile the Vera files
% vera -cmp -vcs_mx vera_files

If you are using a multiple main flow (project-based approach), then do the following:
% vera -cmp -cs filename.vr % vera -proj -vcs_mx filename.proj

2. Analyze the VHDL files


% vhdlan vhdl_files

While importing VHDL tasks, the vera_mx shell generator will generate a new vhdl shell file vhdltasks_shell.vhd which also needs to be analyzed 3. Compile the Verilog files You must provide two switches to VCS: -mhdl and -vera, or -mhdl and -vera_dbind, When the two switches -mhdl and -vera are used with VCS, the cli option +cli+4 is enabled by default. You can override this cli option for better performance by explicitly providing the options +cli+2, or +cli+3. The effects of the different cli options are: - +cli+2: if the verilog signals in the bottom layers are only to be read (and not written), +cli+2 is sufficient - +cli+3: if the verilog signals in the bottom layers are to be read as well as written, +cli+3 allows you to do so. +cli+3 enables the write capabilities only on wires, not on registers.

Using Vera 2-21

- +cli+4: if you want to read as well as write any verilog signal, (registers as well wires) you do not need to specify any cli option since +cli+4 is enabled by default when the two switches mhdl and -vera are used together. The usage with VCS is as follows:
% vcs -mhdl -vera verilog_files

-vera_dbind is selected when using signal_connect() for dynamic binding.


simv +vera_load=filename.vro |+vera_mload=filename.vrl | +vera_pload=filename.proj

VCS-MX (VHDL on top)


1. In order to compile the Vera file(s) and to generate the corresponding shell file, enter the command:
vera -cmp -sro_mx filename.vr

If you are using a multiple main flow (project based approach), then do the following:
vera -cmp -cs filename.vr vera -proj -sro_mx filename.proj

2. Analyze all the Verilog files.


vlogan filename.v...filenameN.v

3. Analyze all the required VHDL files, including the shell file
vhdlan filename1.vhd ...filenameN.vhd

4. In order to elaborate the design, give the following command:


scs configuration_name -verilogcomp "[+cli+n]"

Using Vera 2-22

Refer to the VCS-MX User Guide for more information on using Verilog and VHDL. Note: +cli+n enables capabilities incrementally, that is, +cli+2 enables +cli+1 capabilities, +cli+3 enables +cli+2 capabilities and so on. +cli+n is not necessary if the Vera testbench is connecting Vera signals to VHDL signals in the top VHDL layer. The top layer VHDL signals can be driven and sampled, without giving the +cli option. +cli+1 is sufficient if the Vera testbench is neither driving nor sampling an MHDL signal. Use +cli+2 if the Vera testbench is just sampling a Verilog signal. Use +cli+3 if the Vera testbench is driving a Verilog net. Use +cli+4 if the Vera testbench is driving a Verilog register. 5. Include the vera_load=filename.vro, vera_mload=filename.vrl or the vera_pload=filename.proj options in the vera.ini file. 6. If there were no errors, an executable scsim will be generated. scsim can be executed by entering the command:
scsim -include filename

where filename contains the commands for scsim. Refer to the VCS User Guide for Information about the command line options available with scsim. Note: Use +cli+n option judiciously, since this affects performance.

Using Vera 2-23

When connecting HDL signals statically or dynamically, always provide absolute path names (that is, do not use any relative path names). In order to dynamically connect a Vera signal to a mixed HDL signal, use the signal_connect() system task in the same way as you would for other simulators.

Simplified Use Model for VCS-MX


When compiling Vera files with the -mx switch, the design type no longer has to be specified. The following command line is used for Verilog top mixed designs, VHDL top mixed designs as well as pure VHDL designs.
vera -cmp -mx vera_file

Figure 2-3 illustrates the flow:

Using Vera 2-24

Figure 2-3
vera -cmp -mx Vera files

Verilog Task shell

VHDL shell

VHDL task shell

vdlan If any hdl_task is being imported vlogan Since there is no -mhdl option in this VCS-MX model, there will not be any default enabling of cli capabilities No -vera simv

vcs +cli+n -mhdl

All the features described in VCS-MX (Verilog on top) on page 2-21 and VCS-MX (VHDL on top) on page 2-22 are supported with this simplified use model. With this use model, an imported hdl_task is a vhdl_task by default. If the user wants to import a Verilog task, it needs to be explicitly specified as follows:
hdl_task my_task {verilog_task} top.my_veri_task;

Using Vera 2-25

ModelSim SE
1. Compile the Vera files
vera -cmp -mti filename.vr

This generates the filename.vro and the vhdl shell files. 2. Analyze the Verilog files
vlog *.v

3. Analyze the vhdl files including the vhdl shell file


vcom *.vhd

4. Run the simulation


vsim -c configuration_name

NC-Sim
1. Create libvpi.so 2. Set SSI_LIB_FILES to make ncsim load vera_ncvl_mx.dl instead of the default vera.dl
setenv SSI_LIB_FILES $VERA_HOME/lib/vera_ncv1_mc.dl

3. Compile Vera files.


vera -cmp -ncvl_mx filename.vr

This generates a Verilog shell file and the vro file. The switch -ncvl_mx should be used only for the Verilog-top mixed design flow with NC-Sim. As of now, VHDL-top mixed design flow is not supported with NC-Sim. 4. Analyze the verilog files including the verilog shell file
ncvlog *.v

Using Vera 2-26

5. Analyze the VHDL files


ncvhd *.vhdl

6. Elaborate the design


ncelab work.top module

7. Run the simulation


ncsim work.top module

Limitations and Unsupported Features


The following is not supported: VHDL top flow with NC-Sim Importing Verilog tasks defined below the VHDL layer. Exporting Vera tasks to the mixed HDL side.

SystemC-based Flow
OpenVera supports integration with SystemC. The integration supports: statically bound signals, calling OpenVera tasks from SystemC, calling non-time consuming SystemC tasks from OpenVera.

OpenVera is supplied as a static library. This library, along with the SystemC library, is linked with your SystemC code to form a single executable. This executable is able to load and run OpenVera vro files.

Using Vera 2-27

Creating an OpenVera Interface


To connect OpenVera to a SystemC design, you need to specify an appropriate collection of interfaces in the OpenVera program file. An interface is a list of signals that crosses the SystemC/OpenVera boundary. SystemC and OpenVera types are not directly equivalent so a mapping from one type to the other must be performed. For example, assume you wish to test a SystemC module named Device, which has the following declaration.
SC_MODULE(Device){ sc_in<sc_lv<8> > sig1; sc_out<sc_logic> sig2; sc_in<bool> clk; ... }

This module has an 8-bit logic input, a 1-bit logic output, and a boolean clock. Assuming you wish to have access to all three of these signals from OpenVera, you would define an interface in your OpenVera program, as illustrated below. Except for clk, which is always an input signal, the signal directions are reversed (for example, an sc_in signal is a OpenVera output signal). The skew constants are of course arbitrary and not significant for this example.
interface ifc1 { output [7:0] sig1 PHOLD #3; input sig2 NSAMPLE #-3; input clk CLOCK hdl_node "{bool}"; }

The default mapping from an OpenVera type to a SystemC type is to sc_logic for bit vectors of width 1 and to sc_lv for bit vectors wider than 1 bit. The types bool, sc_bv, sc_int, sc_uint, sc_bigint, sc_biguint can be specified using the hdl_node construct as shown in the example above.

Using Vera 2-28

Running SystemC with OpenVera


Note: The SystemC integration does not support dynamically bound signals or integration with a third language. This stage assumes you have created an OpenVera file named test.vr and a SystemC file named test.cpp. The OpenVera file should have an appropriate interface and presumably include code to interact with the SystemC signals. The steps to compile and run the code are as follows: 1. Generate the shell file, the top file and the vro. The shell file is a SystemC header which contains the routines to communicate with the OpenVera runtime. Within it is a SystemC module called vera_shell, which you must instantiate and connect to the SystemC signals. The top file is an example of instantiating the vera_shell module. The top file always requires some modification to suit the particular design being tested. The command to generate these files is:
% vera -systemc -cmp -top test.vr

The files produced are: - test_shell.h: the OpenVera shell include file for Vera - test_top.cpp: the top testbench - test.vro: the executable for Vera If the top file has been modified and does not need regenerating, the -top argument should be removed.

Using Vera 2-29

2. Modify the top file. The top file assumes your module is named test. You should rename test to the name of your module and include the header for this module in the top file. For this example you would change test to Device and include Device.h. This assumes Device.h contains the declaration of the Device module. The signal connections should generally be correct for all but clock signals. The generated top file includes a SystemC clock which it ties to the OpenVera SystemClock. This clock should often be tied to the SystemC modules clk signal and in this example the OpenVera interface clk signal. 3. The OpenVera runtime library expects a set of runtime arguments. These are forwarded by the generated top file from the command line of the C++ executable using:
VeraSystemC::SetArguments(argc, argv)

where argc and argv are the arguments to sc_main. These arguments can of course be modified, and/or hard-wired at your discretion but no modifications should be required. 4. Compile test_top.cpp. The top file should be compiled into a test_top.o file. The test_top.cpp includes test_shell.h which includes header files stored in $VERA_HOME/include/systemc. These instructions are assuming $SYSTEMC has been set to the location of the users SystemC installation. This environment variable is not otherwise necessary. Using gcc, the command to compile the file is:
g++ -g -I. -I$VERA_HOME/include/systemc \ -I$SYSTEMC/include -c test_top.cpp

5. Compile your code. This step should be very similar to compiling test_top.cpp. The OpenVera include directory is of course unnecessary.

Using Vera 2-30

6. Link the final executable. The executable should include the SystemC library, the OpenVera library for SystemC, test_top.o and the your SystemC code. The OpenVera library for SystemC is located at $VERA_HOME/lib/systemc/libVERA.a. Depending on the machine, additional system libraries may be required. The commands below assume the final executable will be called run.x. On Solaris:
g++ -g -L$VERA_HOME/lib/systemc \ -L$SYSTEMC/lib-gccsparcOS5 -o run.x \ test.o test_top.o -lVERA -lsystemc \ -lm -lsocket -lnsl -ldl

Note: For machines not qualified for the Synopsys configuration, the -ldl and -lnsl need to be added to the g++ link command. On Linux:
g++ -g -L$VERA_HOME/lib/systemc \ -L$SYSTEMC/lib-linux -o run.x \ test.o test_top.o -lVERA -lsystemc -lm -ldl

7. Run the simulation. The executable forwards arguments to the OpenVera runtime. The OpenVera runtime expects to be told the location of vro files. The command to run OpenVera with just test.vro would be:
run.x +vera_load=test.vro

Using Vera 2-31

Calling OpenVera Tasks from SystemC


The above description does not include imported and exported functions. To call an OpenVera task from SystemC, you must prefix the declaration in OpenVera with the export keyword. This causes the generated vera_shell module to contain a task, task_taskname, with mapped arguments. For example, the statement:
export task parity(reg [47:0] x)

creates a member function of the generated module declared using:


static void task_parity(sc_lv<48> x, sc_event *pDone=0)

The sc_event pointer, pDone, is an optional argument. OpenVera calls pDone->notify() when the OpenVera task parity() has completed execution. A null value indicates that no notification is necessary. Var arguments are supported. Only bit-vector and integer types are supported.

Calling SystemC from OpenVera


To call a SystemC task from OpenVera, you must add a declaration of the form to the OpenVera code:
hdl_task vera_taskname (arguments) "C_taskname";

In the generated header this will produce a line of the form:


extern void C_taskname (arguments);

where the OpenVera arguments have been mapped to C++ arguments.

Using Vera 2-32

You must then write a task matching the generated extern declarations.

Using Vera 2-33

Using Vera 2-34

3
Compiling and Running Testbenches 3
This chapter describes how to compile and run testbenches using Vera. It includes the following sections: Compiler Command Line Options Running Vera with a Simulator Runtime Options Passing Data at Runtime Referencing Variables External Declaration of Subroutines

Compiling and Running Testbenches 3-1

Compiler Command Line Options


The Vera compiler accepts two types of options: general options, which do not involve the compilation of an OpenVera source code file, and compilation options, which are used when compiling an OpenVera source code file.

General Options
General options can be passed to the Vera compiler to return tool information and to create template files. When these options are used, the OpenVera source code files are not compiled and therefore no Vera object files are created. The syntax to invoke the compiler is:
vera general_options [input_filename ]

general_options is one or more of the following:


Option
-help -pp -print -proj -rvm_version -tem -v -V -vcon -vmc

Definition
Lists valid Vera executable options Invokes the Vera preprocessor Creates a PostScript file Creates Vera shell files from the project file displays rvm version Invokes the Vera template generator Returns the Vera compiler version Prints complete version information For multiple module support Prints version information for the Vera virtual machine.

-help Lists all the valid Vera executable options.

Compiling and Running Testbenches 3-2

-pp input_filename invokes the Vera preprocessor on the input file. The preprocessor output file is written to stdout. -D macro_name=value specifies a text macro. See -D macro_name=value. To invoke the ANSI preprocessor, use the -ansi switch. -print filename1 filename2 ... filenameN Prints the specified files to a PostScript file called filename.ps. By default, lines are not wrapped. To specify a line wrap after a certain number of characters, use the -w switch: -w number where number is the number of characters allowed before lines are wrapped. -Pprinter specifies a printer in the network. -proj project_filename Generates a Vera shell file called modulename_shell.v for each module (for VHDL the name is modulename_proj_shell.vhd) contained in the Vera project file. -rvm_version Displays the RVM version available in the Vera installation:
vera -rvm_version RVM Class Library Version: 8.5.3

-tem verilog_filename invokes the Vera template generator (see The Template Generator on page 1-7). -v Prints the version number of the Vera installation. For example, a version number will look similar to: 5.1.0

Compiling and Running Testbenches 3-3

-V Prints complete version information. For example, a complete version will look similar to: VERA 5.1.0 (Beta3) -vcon Generates a .vcon file for use with multiple module support. -vmc Prints version information for the Vera virtual machine, that is, the VRO file version. For example, a VRO version may look like: 4.1

Compilation Options
The Vera compiler is primarily used to compile Vera source code using the -cmp option. The syntax is:
vera -cmp compiler_options -simulator input_filename output_filename/output_directory_name

compiler_options: Is one or more of the following:


Option
-all_force -ansi -aop -covg_compat -D -dep_check -dyn -f -F -g

Definition
all signals become forceable. Invokes the ansi preprocessor. Compiles aspect oriented extensions files. Compiles files in pre-2005.12 semantics for coverage. Specifies a macro name. Detects files with circular dependencies. Used to ensure that the VDEO has a unique entry point defined. Automates capturing file dependencies across multiple files. Automates capturing file dependencies across multiple files. Includes debugger information

Compiling and Running Testbenches 3-4

Option
-h -H -HC -HCnu -hnu -Hnu -I -i -i_skew -local

Definition
Updates .vrh file Updates .vrh file Updates .vrh file and compiles .vro file Updates .vrh file only if there have been changes and compiles .vro file Updates .vrh file only if there have been changes. Compiles Turns on the -H switch and updates the .vrh file only if it has changed Adds a specified path to the search path for include files. Produces an ASCII interface definition. Specifies default input skew. Includes local variables in auto generated header files when it is specified in combination with one of the header file generation options. All the text that is printed to stdout/stderr is written to a specified log file. Sets the maximum number of errors before compilation failure. No dependency graph generated when using -dep_check. Disables pack warning messages for packing of a null object. Outputs dependencies for source files to standard output. Compiles in quiet mode, without a header. Compiles files in pre-6.0 compatibility mode. Generates SystemC header file. Enables old typedef usage. Generates a VHDL test_top file. Used in conjunction with the -y in conjunction. The compiler will compile the program_file.vr and the files this .vr file is dependent upon. Preprocesses file.vr in non-ANSI mode invokes license polling Generates an IP core. Applies assignment-style widening to expressions passed as task/function arguments. Compiles all .vr files in specified directory.

-log_file -max_error -no_dep_graph -no_warn_null -print_deps -q -random_compat -systemc -tdef -top -top_file

-traditional +ver+lic+wait -vip -widen_args -y

Compiling and Running Testbenches 3-5

-all_force By default, all signals become forcible when compiling with the -all_force compile-time option. Therefore, the force attribute does not have to be present on the interface signal for the signal to be forced. Note: Force and release are only supported for pure Verilog designs. -ansi Preprocesses the Vera source code in ANSI mode. -aop Supports Veras Aspect-Oriented Extensions. Users need to adopt a methodology that partitions all introductions and advice in separate files from the class definitions, program blocks, etc. Only introductions and advice may be present in such files. These files must be compiled with the -aop switch. The -aop switch may not be used on other Vera code blocks.
vera -cmp -aop cov1.vr vera -cmp -aop cov2.vr vera -cmp -aop cov3.vr

The resulting aspect .vro files must be loaded before any non-aspect .vro files. This may be done by either listing the .vro files first in the .vrl file, or by setting the vera_aspects runtime argument to the file names: (see vera_aspects on page 3-35)
simv +vera_aspects=cov1.vro,cov2.vro,cov3.vro

Note: The same AOP .vro file should not be listed in both the +vera_aspect list and in the .vrl file.

Compiling and Running Testbenches 3-6

Example 3-1
// foo.vr class foo { integer x; } #include "foo.vrh" // fooAop.vr extends fooAop(foo) { before task new() { printf("New called\n"); } } // top.vr: #include "foo.vrh"// do not include fooAop.vrh program top { foo f; f = new(); }

compilation:
vera -cmp -HC foo.vr vera -cmp -aop fooAop.vr vera -cmp top.vr

Note: When using the automated build option, the -aop switch should be specified within the file.list and not on the command line. Using the above example:
# file.list -HC foo.vr -aop fooAop.vr top.vr vera -cmp -f file.list -dep_check

Creating the .vrl file: Option 1:


// object.vrl // aop files must be first fooAop.vro foo.vro top.vro

Compiling and Running Testbenches 3-7

Option 2:
// object.vrl // must use +vera_aspects=fooAop.vro on simulation // command line foo.vro top.vro

Simulation Option 1:
vera_cs +vera_mload=object.vrl

Option 2:
vera_cs +vera_mload=object.vrl +vera_aspects=fooAop.vro

The vera_aspects runtime option (see vera_aspects on page 3-35) applies to all OpenVera main programs. If per-main aspects are required in a multiple main simulation, the aspect .vro files should be specified in the project file. The aspect files for a program must be specified first in the program's .vro list:
main Master master_cov_aspect.vro ##coverage aspect for master master.vro main slave slave_cov_aspect.vro ##coverage aspect for slave slave.vro

Note: When using VIP, or attributes to load .vro files, use the +vera_aspects runtime option as described above to ensure that the aspect .vro files are loaded first. The woven code itself can also have semantic errors or introduce semantic errors, for example, a reference that was resolved to an integer variable in a super class now resolves to a string variable.

Compiling and Running Testbenches 3-8

In these cases, either the compiler, or the runtime loader prints error messages that describe the extension, statement, and target scope that caused the error. -covg_compat The -covg_compat option enables Vera to compile the source file in the old (pre-Vera X.2005.12) semantics for coverage and disables, all the new Vera X.2005.12 coverage features such as: - SV style auto binning - New semantics for cross bins - Accurate cross coverage computation - Accurate hole analysis for cover points and crosses - Default coverage goal changed to 100 percent
vera cmp covg_compat [-other_compile_options] file.vr

All .vro files given as input at runtime must have been compiled with this option. If not, the runtime loader issues an error message. The database generated using the option cannot be merged with a database generated without using this option and vice versa. -D macro_name=value Specifies a text macro, where macro_name is the string of text to be substituted for and the text macro is optionally set to value. Text macros defined at compile time are particularly useful when using conditional compilation directives.

Compiling and Running Testbenches 3-9

-dep_check Enables dependency analysis and incremental compilation. Detects files with circular dependencies and issues an error message when Vera cannot determine which file to compile first. -dyn Is used to compile a Vera file into a VDEO. No other switches may be used. This will produce a dynamic.vro file, which can then be loaded at runtime using the vLoad() system call. -f The f option must be supplied with a filename. This file includes a list of all the source files to be compiled. The recommendation is to append the filename with the .list extension to indicate that it is a Vera source list file. -f works equally well with both relative and absolute path names. For example:
------------------------

#file.list topTest.vr packet.vr checker.vr -----------------------vera -cmp -f file.list

-F The -F works similarly to the -f option but the supplied path is prepended to all source files contained within the file list. Since the supplied path is prepended, it is recommended that absolute pathnames not be used within the list file when using -F. Assuming file.list:
tb1.vr tb2.vr

Compiling and Running Testbenches 3-10

The command,
vera -cmp -F $MY_FILES_DIR/files.list

results in Vera looking within the $MY_FILES_DIR for tb1.vr and tb2.vr. Usage Note More than one F option can be specified within a list file. This can also be used in conjunction with f Assume the following directory structure:
Rootdir file.list out // directory rootdir/include include.list tb1.vr rootdir/library library.list tb2.vr tb3.vr file.list -F include/include.list -F library/library.list include.list tb1.vr library.list tb2.vr tb3.vr Compile Command: vera -cmp -HC -f file.list out

File List Structure The following guidelines pertain to the contents of the list file. The suggested naming convention is <fileBaseName.list>. The .list is not required as the full name is specified when giving the f and F options.

Compiling and Running Testbenches 3-11

Rules All Vera compiler options are supported when specified with a source file. (-h, -H, -HC, -hnu, -Hnu, -HCnu, -y, -F, -f, -max_error, -g, -i_skew, - q, -top, -I). These options only apply to the source file which is specified. For example, if q is used the quiet mode only effects the single source file, not the entire compilation. Comments are prefixed with #. It has to be at the start of a line.

When using the file.list, all options on the command line are considered general options that apply to all the files to be compiled. Source file specific options are set within the file.list. General options are specified on the command line and with the 'opts:' command within the file list. Within a list file, a user can specify general options that effect all subsequent source files. The option to do this is with the list file command 'opts:' These general options apply until another opts: command is reached within the file. At this point the previous 'opts:' option is no longer applied. General options supplied via the command line apply to all files unless overridden by local options, while general options supplied via 'opts:' are applied to all files until another 'opts:' command is found. All general options can be overridden with local options supplied at the individual source file level.
#file.list opts: -I.. myfile.vr opts: -I. -HC foo.vr -h bar.vr opts: -I../include -I../source test.vr vera -cmp -f file.list

In the above example the following compilation steps occur:


vera -cmp -I.. myfile.vr

Compiling and Running Testbenches 3-12

vera -cmp -I. -HC foo.vr vera -cmp -I. -h bar.vr vera -cmp -I../include -I../source test.vr

Local options can only be set within the file.list.


vera -cmp -I. -Ilibrary -f file.list

file.list
-I/etc -HC packet.vr -y library

The above example generates the following compilation steps with a single license checkout.
# all .vr files in library are compiled vera -cmp -I. -Ilibrary -y library vera -cmp -I. -Ilibrary -I/etc -HC packet.vr

The user may also specify a general output directory or output directories per file: file.list:
# example of output directory -y library library/out # example of output file -I/etc -HC packet.vr out

Usage Notes - Individual source options are applied in addition to the general source options. Should a conflict exist between the general and individual settings, a warning message is printed, and the individual options override the general options - The output directory or output file specified in the list file will override the generic output directory (what is given on command line), if specified.

Compiling and Running Testbenches 3-13

- The list file may contain environment variables for path names. For example
-y $TESTDIR $TESTDIR/out

-g Generates debugging information. You must use this switch if you intend to use the graphical debugger. -h Updates the .vrh header file. -H Generates header files (.vrh) with #include and extern declaration from the Vera file (.vr) This switch does not generate a Vera object file (.vro). An additional compilation step without this switch is required to complete the Vera file compilation. For example:
vera -cmp -H test.vr vera -cmp test.vr // generates test.vrh file // generates test.vro file

Note: Both -H and -h, generate header files with the same name, therefore, they override each other. Furthermore, the H and h switches are mutually exclusive. The Vera compiler generates an error message if you try to compile with both switches.

Compiling and Running Testbenches 3-14

Example 3-2 Example 1


//file: B.vr class B { ... ... } //file: A.vr: #include "B.vrh" class A { B b; ... ... }

Compile command (note the order):


vera -cmp -H A.vr

The generated header file A.vrh includes the #include B.vrh statement. The header file is shown below:
//////////////////////////////////////////////// // Vera Header file created from A.vr //////////////////////////////////////////////// #ifndef INC__TMP_A_VRH #define INC__TMP_A_VRH #include "B.vrh" extern class A { integer a1; B b; } #endif

Example 3-3 Example 2


//file: B.vr extern integer i; extern class C {....} class B { ... ... }

Compiling and Running Testbenches 3-15

Compile command:
vera -cmp -H B.vr

The generated header file includes extern declarations in the B.vr file. The header file is shown below:
////////////////////////////////////////////////// // Vera Header file created from B.vr ////////////////////////////////////////////////// #ifndef INC__TMP_B_VRH #define INC__TMP_B_VRH extern integer i; extern class C {... } extern class B { integer i; } #endif

-HC The -HC option automatically creates a header file with extern declarations and include directives for files included in the source files. It updates the .vrh file. An object file is generated. Example
vera -cmp -HC a.vr

will generate the following files:


a.vrh a.vro

-HCnu The -HCnu option automatically creates a header file with extern declarations and include directives for files included in the source files. It updates the .vrh file only if it has changed. An object file is generated.

Compiling and Running Testbenches 3-16

For example:
vera -cmp -HCnu a.vr

will generate the following files


a.vrh a.vro //if it has changed

-hnu The -hnu option functions like the -h option except that it only updates the .vrh file if there are changes to it. -Hnu Updates the .vrh header file only if it has changed. -I The -I option adds a specified path to the search path for include files. Syntax
-Idirectory

directory is the absolute or relative path to the directory you want to add to your search path. Include files are declared as follows:
#include "filename" #include <filename>

However, if there are two files with the same name, for example, a foo.h in the current directory and a foo.h in another directory, then these files must be declared as follows:
#include "foo.h" // Use "" when the file to be included is in same // directory where the file to be compiled is located. #include <foo.h> // Use <> when the file to be included is another // directory. Used in conjunction with -I option.

Compiling and Running Testbenches 3-17

On the vera -cmp command line you must then specify the path to the <foo.h> file. For example:
vera -cmp -I.. test.vr

-i Generates an ASCII file (.vri) containing the interface definition. This interface specification produces the corresponding generated interface file:
input [31:0] data_in PSAMPLE 1 output [31:0] ack PHOLD 0 inout [1:0] data_out PSAMPLE 0 PHOLD 1 input if_0 data_in 32 PSAMPLE 1 output if_0 ack 32 PHOLD 0 inout if_0 data_out 1 PSAMPLE 0 PHOLD 1

-i_skew The -i_skew option allows you to specify a default input skew for all interface input and inout signals that do not have explicit skews defined in their interface declarations on the command line. Input and inout signals that do have explicit skews defined in their interface declarations continue to use their explicitly specified skews for their samples and expects. Signals that are dynamically bound at run time using signal_connect() are not affected by the default skew option. Syntax
-i_skew number

number can be any negative integer or 0. If a positive number is specified, a warning will result. Example
vera -cmp -g -i_skew -1 -q -max_error 2 tb2.vr

Compiling and Running Testbenches 3-18

-local When used in combination with one of the header file generation options (e.g -H, -h), local variables will be included in the resulting auto-generated .vrh file. -log_file When -log_file filename is specified with vera -cmp, all the text that is printed to stdout/stderr is written to a specified log file. For example:
vera -cmp -log_file log test1.vr

Text is written to the specified file, log. -max_error number The -max_error_number option specifies the maximum number of errors the compiler can encounter before the compilation fails. -no_dep_graph The no_dep_graph bypasses the generation of the dependency graph when using the -dep_check option (see -dep_check on page 3-10). Its function is to expedite compiles of large file sets when dep_check has previously been run on a set of files. Use with caution since, if the directory structure or dependencies of the files change, the build will not succeed. Considering the previous example, say you have already executed the command:
vera -cmp -f files.list -dep_check -print_deps.

Next, the tb1.vr file is modified, but the #include directives are not changed and the #include files themselves are not changed, then with the use of no_dep_graph:
vera -cmp -f files.list -dep_check -print_deps -no_dep_graph

Compiling and Running Testbenches 3-19

The output will be


VERA info: dependency graph is not being built. Using the old dependency graph. Dependencies: tb1.vro: tb1.vr tb2.vrh tb2.vrh: tb2.vr tb2.vrh: up-to-date tb1.vro: building ... command: tb1.vr VERA info: compilation errors: 0

-no_warn_null -no_warn_null disables warning messages that are given when objects contained in the object being packed are NULL. It also disables randomization warning messages that are given when objects contained in the object being randomized are NULL. -print_deps The print_deps is supplied with -dep_check telling the Vera compiler to output the dependencies for the source files to standard out or to a user specified file. Syntax
vera -cmp -f file.list -dep_check -print_deps[=filename]

filename is the name of the file where the user wants the results to be printed to. Example 3-4
vera -cmp -f file.list -dep_check -print_deps= "file_dep_report"

The above command line specifies that the source file dependencies are to be printed to a file named Makefile. Note that filename is optional. If filename is not specified, the source dependencies will print to stdout.

Compiling and Running Testbenches 3-20

Example 3-5
vera -cmp -f file.list -dep_check -print_deps

This command line will result in the source dependencies being printed to stdout. Assume tb1.vr has a dependency on tb2.vrh. file.list: tb1.vr tb2.vr
vera -cmp -HC -f file.list -dep_check -print_deps VERA info: building dependency graph ... Dependencies: tb1.vro: tb1.vr tb2.vrh tb1.vrh: tb1.vr tb2.vrh tb2.vro: tb2.vr tb2.vrh: tb2.vr tb2.vro: building ... command: -HC tb2.vr tb2.vrh: up-to-date tb1.vro: building ... command: -HC tb1.vr tb1.vrh: up-to-date VERA info: compilation errors: 0

Running the command again, the output will be:


VERA info: building dependency graph ... Dependencies: tb1.vro: tb1.vr tb2.vrh tb1.vrh: tb1.vr tb2.vrh tb2.vro: tb2.vr tb2.vrh: tb2.vr tb2.vro: up-to-date tb2.vrh: up-to-date tb1.vro: up-to-date tb1.vrh: up-to-date VERA info: all targets are up to date; no need to build anything.

Compiling and Running Testbenches 3-21

Without, -print_deps, the output will be:


VERA info: building dependency graph ... tb2.vro: up-to-date tb2.vrh: up-to-date tb1.vro: up-to-date tb1.vrh: up-to-date VERA info: all targets are up to date; no need to build anything..

Handling of circular dependencies: -dep_check will detect files with circular dependencies and report an error message indicating the issue: For instance, if tb1.vr includes tb2.vrh and tb2.vr includes tb1.vrh and the file.list is: -H tb1.vr -H tb2.vr Vera cannot determine which one to compile first so, Vera gives the following error message:
VERA error: cycle detected, cycle is: "tb1.vrh" <== "tb2.vrh" <== "tb1.vrh"

-q compiles the code in quiet mode. When the compiler is run in quiet mode, the header information is shortened and limited to only compile information. -random_compat Random value generation changed as of v6.0 and is not compatible with pre-6.0 versions of Vera. To compile older testbenches, add this switch to the compile command:
vera -cmp -random_compat ...[file.vr]

This switch applies to the whole testbench; you cannot mix new and old random values.

Compiling and Running Testbenches 3-22

-systemc Generates the shell file, which is a SystemC header containing the routines that communicate with Vera runtime. -tdef Enables the old usage of typedef so that existing code can be compiled, which is useful in compiling existing Vera code. In Vera releases before 4.0, typedef could sometimes be used in place of an extern class definition. In Vera 4.0 and later, typedef is a forward reference mechanism within a compilation file. Note: This switch should not be used for new Vera development as it can sometimes cause compilation errors. -top_file When using -y in conjunction with -top_file, the compiler will compile the program_file.vr and the files this .vr file is dependent upon. If -top_file is not specified, then the compiler compiles all the files in the specified in the directory, even those that are irrelevant to program file. -traditional Preprocesses file.vr in non-ANSI mode. +vera+lic+wait Invokes license polling. You cannot release a license temporarily when the process is stopped and re-acquire it when the process is restarted. May also be used as a runtime option (see page 3-31).

Compiling and Running Testbenches 3-23

-vip Generates encrypted Vera source files that can be used as IP cores (see Chapter 14, Testbenches for Verification Intellectual Property). -widen_args Applies assignment-style widening to expressions passed as task/function arguments. If you do not use this switch, you must set the environment variable VERA_WIDEN_ARGS to a non-zero value. -y The y option automatically compiles all .vr files in the specified directory. For example:
vera -cmp -HC -y $MY_VR_FILES_DIR

Vera will compile all the .vr files in $MY_VR_FILES_DIR with the -HC option. The y option supports the use of -dep_check, -print_deps and -no_dep_graph. Use of these additional options will result in Vera determining the dependencies for all of the .vr files in the directory along with incremental compilation. Usage note - More than one y option is allowed within the list file. It, however, is not legal syntax to include both f and y on the command line.

Compiling and Running Testbenches 3-24

simulator: is one of the following:


Simulator
Verilog VHDL SystemC Vera Standalone

Switch
-vlog -mti, -sro, -nc_vhdl -systemc -cs

Note: Setting the VERA_SIMULATOR environment variable allows users to change the default simulator when compiling Vera programs. The simulator specific switches (for example, -vlog, -cs, -mti, -nc_vhdl, -sro) do not then have to be included on the compile command line. input_filename Is the name of the Vera source file being compiled. output_filename Is the prefix of the output file. When the -cmp option is invoked, the compiler generates the object file output_filename.vro and the shell file output_filename.vshell. If the output file is not specified, the prefix of the input file is used.The following compiler options control the generation of the Vera shell file.
Option
-alim

Definition
Defines the maximum variable size for which mirrored HDL variables will be created. Includes the specified .vcon file Sets the module name in the HDL shell.

-cfg -shell

Compiling and Running Testbenches 3-25

Option
-timescale -top -vlog

Definition
Specifies a timescale Generates a VHDL test_top file Names the Vera shell file filename_shell.v

-alim number Defines the maximum variable size for which mirrored HDL variables will be created. The default value is 0. If 0, it indicates that no global variables are declared in the shell files and Vera will not create any mirrored HDL variables. This option is for the shell generation. That is, it limits the global variables propagated through to the HDL side. If you add in any global variables, you do not need to recompile the HDL, since the shell is unchanged. -cfg filename Includes information from a specified configuration file (.vcon) in the resultant shell file. Where filename specifies the .vcon file to be included. When the -cfg option is used, the specified configuration file is read and included in the shell file. This allows you to generate a clock with Vera using the clock statement within a .vcon file and include it in your simulation. -shell module_name Sets the module name in the HDL shell. If omitted, the module is named vera_shell. -timescale scale Indicates the simulation time unit for the simulator. timescale is a verilog key word.

Compiling and Running Testbenches 3-26

This option generates the following statement at the top of the Vera shell file:
timescale scale

When you use the Vera delay() system task, or have skews on interface signals, you should compile the Vera source file containing the program block with this option. The scale value sets the units to which the delay(), or skew, refers. Example 3-6
%vera -cmp -timescale 1ns/100ps test.vr

Note: Verilog users: If you do not compile with -timescale, the Verilog simulator uses the timescale value declared in the most recently compiled .v file, and this value many not be in the units you wish. If the units are not correct, Vera may issue a runtime error telling you to decrease the timescale resolution (for example, from a resolution of 100ps to 10ps). -top Generates a test_top file for VHDL and SystemC designs. -vlog Creates a Vera shell file named filename_shell.v. When -vlog is not included on the command line, the compiler assumes Verilog and creates a Vera shell file named filename.vshell.

Compiling and Running Testbenches 3-27

Running Vera with a Simulator


This section lists the runtime options and arguments applicable to a Vera simulation. To run Vera with a simulator, enter the following command:
simulator [switch_+arg]

where: simulator Is the simulator executable linked with Vera (specify the full path if it is not in your search path). To run Vera as a standalone, enter vera_cs as the simulator name. switch_+arg Is any valid simulator or Vera switch/+argument (See Runtime Options on page 3-28 for the list of +arguments).

Runtime Options
There are two types of runtime options: On and Off Options: parameters with a Boolean value, that is, either on or off. Options are set on by just mentioning them. Options requiring user-specified values: parameters for which you must specify a value (either an integer or a string).

Compiling and Running Testbenches 3-28

Runtime options can either appear as +plus arguments on the simulator command line (Verilog simulators only) or in the vera.ini file: An On and Off option can be set "on" by just mentioning it.
+vera_stop_on_error

As +plus arguments on a simulator command line, the parameter name and value can be separated by an equals sign or an underscore:
+vera_load=adder.vro +vera_load_adder.vro

A space is not allowed anywhere in a plus argument. In the vera.ini file, the + is omitted, and the parameter name and value can be separated by either an equals sign, an underscore or a space:
vera_load=adder.vro

Note: The file from which Vera reads initialization values is named vera.ini by default. An alternative filename may be specified with the VERA_INI environment variable. Vera attempts to open this file first in the current working directory, then in the $VERA_HOME directory.

Compiling and Running Testbenches 3-29

On and Off Options


The following are the on and off runtime options: vera_continue_on_error Causes the simulation to continue after a verification error is encountered. This option causes the simulation to continue when verification errors (such as failed expects) occur. This option overrides the vera_exit_on_error option. vera_debug_on_error Invokes a debugger when a verification error (such as a failed expect) is encountered. This option determines the debugger used when a verification error is encountered. If the HDL simulator has control when the error occurs, the simulators debugger is invoked. If Vera has control when the error occurs, Veras debugger is invoked. If this option is not used, the behavior depends on the particular HDL simulator. vera_debug_on_int When the simulation is running, the debugger will start after you press Ctrl-C. vera_debug_on_start Causes the Vera debugger to be accessed at the start of the main Vera program. If you are using multiple modules, this switch places a breakpoint at the start of each separate main program. vera_disable_random_stability Disables all of the random stability modes. vera_disable_final_report Disables printing of the final report. By default, this option is false.

Compiling and Running Testbenches 3-30

vera_dyn Use this option if you intend to dynamically load a VDEO at runtime. vera_enable_mprint Allows you to use Veras main name error messaging capabilities. vera_exit_on_error [= value] Causes the simulation to be terminated when a simulation error is encountered. Default value is 1. vera_full_conflict_info Causes verification error messages to include a context stack trace. For example:
Last Driver: CALL in program test_my_chip (tst_chip.vr, line 47, cycle 0); READY in task_with_port handshake (hs_tasks.vr, line 18, cycle 1)

vera_interactive_plot In an interactive simulation, you must specify this option when using vera_plot(), otherwise vera_plot() will dump in post-processing mode only. vera+lic+wait Invokes license polling. You cannot release a license temporarily when the process is stopped and re-acquire it when the process is restarted. May also be used as a compile time option (see page 3-23). vera_main_name Yields the current main program name.

Compiling and Running Testbenches 3-31

vera_no_hdl_task_semaphore Overrides the automatic blocking and queuing of HDL task calls. When set, a fatal error occurs when there is a collision. vera_path_sep Yields the instance path separator for the current simulator (read only). vera_profile_object Enables memory profiling. Note: vera_profile_object and vera_profile_object_verbose are mutually exclusive. If both are specified, vera_profile_object takes precedence and the unfreed object trace table is not included. vera_profile_object_verbose Reports the class name, the number of objects of this class that have been newed and not freed, and the stack trace of the location for each location of unfreed objects. In addition, records the total number of handles referencing these objects. Note: vera_profile_object_verbose and vera_profile_object are mutually exclusive. If both are specified, vera_profile_object takes precedence and the unfreed object trace table is not included. vera_profile_sort_by_name Instructs Vera to sort entries according to the names of the functions, tasks and programs. By default, entries in the log file are sorted from the highest percentage to the lowest percentage of runtime used.

Compiling and Running Testbenches 3-32

vera_profile_start Instructs Vera to begin profiling. Profiling overhead slows down the simulation slightly. vera_random_seed_automatic The vera_random_seed_automatic runtime option picks a unique value to supply as the first seed used by a testbench. The value is determined by combining the time of day, hostname and process id. This assures that no two simulations will have the same starting seed. The vera_random_seed automatic seed will appear in both the simulation log and the coverage report. When both vera_random_seed_automatic and vera_random_seed are used, a warning message is printed and the vera_random_seed value is used. vera_random_v0 Invokes the random algorithm used in Vera versions 4.1.2 and earlier. This runtime option should only be used if you want to run simulations designed using Vera versions 4.1.2 and earlier and you want the random behavior to be exactly the same as in those simulation runs. Note that the random characteristic using this option may result in non-random behavior for small, power-of-2-choice cases. vera_stop_on_end Stops the simulation and returns control to the HDL shell prompt when a simulation run ends.

Compiling and Running Testbenches 3-33

vera_stop_on_error Causes the simulation to stop immediately when a simulation error is encountered. In addition to normal verification errors, vera_stop_on_error halts the simulation in case of run time errors. The default setting is to execute the remaining code within the present simulation time. vera_sysclk_err The runtime vera_sysclk_error option provides a warning when the SystemClock of the Vera shell is unconnected. When the option is not specified, no warning messages is issued. vera_use_system_random Selects the C random function for the Vera random() call. This option causes random(), urandom(), initstate() and setstate() to use the equivalent libC UNIX functions.

Compiling and Running Testbenches 3-34

Options Requiring User-Specified Values


The following are the runtime options that require users to specify a value. vera_aspects Files compiled using the -aop option must be loaded before any non aspect .vro files. This may be done by either listing the .vro files first in the .vrl file, or by setting vera_aspects to the filenames:
vera -cmp -aop cov1.vr vera -cmp -aop cov2.vr vera -cmp -aop cov3.vr simv +vera_aspects=cov1.vro,cov2.vro,cov3.vro

Note: When using VIP, or attributes to load .vro files, use the +vera_aspects runtime option as described above to ensure that the aspect .vro files are loaded first. Note: The same AOP .vro file should not be listed in both the +vera_aspect list and .vrl file. vera_cache_dir Specifies the directory location of the cache that Vera maintains as an internal disk cache for randomization:
simv +vera_cache_dir=/u/myself/tmp_cache...

This cache improves performance and reduces memory use by re-using randomization problem data from previous runs. The default cache is called .__solver_cache__ in the current working directory.

Compiling and Running Testbenches 3-35

The contents of the Vera cache can be removed at any time, except when Vera is running. vera_coverage_control The coverage_control() system function, coupled with the vera_coverage_control runtime argument, provide a single-point mechanism for enabling/disabling of the coverage collection for all coverage groups or a particular coverage group +vera_coverage_control=COV_STOP/COV_START. vera_debug_show_log The debugger can now display the simulation log file and update its display as the file grows.The debugger displays the log in a horizontal docking window along the bottom of the top window. By default, the log file is not shown. The +vera_debug_show_log option is used to display the log.
+vera_debug_show_log=filename.log

For example, pass this option to the simulator command line


+vera_debug_show_log=vcs.log

Note: VCS also requires a separate option to flush log messages so that they appear in the debugger: +vcs+flush+log To view the log file when vera_debug_show_log has not been used, go to View>LogWindow. This menu item toggles the display of the Log Window (on and off). Once the Log Window is visible, its context menu can be used to load any log file.

Compiling and Running Testbenches 3-36

vera_directc Allows you to attach multiple Vera UDF libraries by specifying them on the command line at runtime. In the case of a dynamically linked flow, the simulation is run with the vera_directc option. vera_enable_checker_trace Enables a debug mode that displays diagnostics when the randomize(VERA_CHECK_MODE) method is called. vera_enable_checker_trace_on_failure Enables a mode that prints trace information only when the randomize(VERA_CHECK_MODE) returns 0. vera_enable_solver_diagnostics Enables the constraint solver diagnostics mode that displays diagnostic information of constraints, which contribute to a solver timeout or a halt at a randomize() call. See Constraint Solver Diagnostics on page 5-111 for more details. vera_enable_solver_diagnostics_on_failure Enable constraint solver diagnostics mode when a solver timeout is issued. See Constraint Solver Diagnostics on page 5-111 for more details. vera_enable_solver_trace Enables a debug mode that displays diagnostics when the randomize() method is called. See Disabling Constraints on page 5-101 for more details. vera_enable_solver_trace_on_failure Enables a mode that prints trace information only when the solver fails to compute a solution, usually due to inconsistent constraints. When the value of the option is 2, the analysis
Compiling and Running Testbenches 3-37

narrows down to the smallest set of inconsistent constraints, thus aiding the debugging process. See Disabling Constraints on page 5-101 for more details. vera_inst_path Yields the shell instance path (read-only parameter). vera_load Specifies the Vera object (.vro) file used with the simulation. vera_mailbox_size Sets the maximum number of mailboxes within the simulation. The default value is 256. vera_mload Specifies a .vrl file that lists multiple Vera object (.vro) files to be used with the simulation. vera_mload_define Specifies a text macro to be applied to the .vrl file:
vera_mload_definemacro_name=value vera_mload_definemacro_name

where macro_name is the string of text to be substituted for and value is an optional value for the text macro. vera_object_filename Specifies the output filename for memory profiling data:
+vera_object_filename=object_report.txt

where object_report.txt can be any valid filename. The following command creates a memory profiling log file called mylog.object:
vera_cs test.vro +vera_profile_object \ +vera_object_filename=mylog.object

Compiling and Running Testbenches 3-38

If +vera_profile_start is included on the runtime command line (see vera_profile_start on page 3-33), the cpu time performance data per task and function will also be added to the end of the file. If not specified, the filename used is vera.object. If the file specified already exists from a prior simulation run, it will be overwritten without warning. vera_pload Specifies a project (.proj) file to be used with the simulation. vera_pload_define Specifies a text macro to be applied to the .proj file:
vera_pload_define macro_name=value vera_pload_define macro_name

where macro_name is the string of text to be substituted for and value is an optional setting for the text macro. Text macros defined at compile time are particularly useful when using conditional compilation directives. vera_plot Specifies the name of the plot file. This parameter overrides the file_name parameter found in the call to vera_plot(). The default filename is vera.isdb. vera_profile_filename The default log file is named vera.prof. This option controls the name of the log file. For example:
+vera_profile_filename=my.log

The profile log file is named my.log instead of vera.prof.

Compiling and Running Testbenches 3-39

vera_profile_interval Sets the frequency of sampling for reporting the memory use of objects in the simulation:
+vera_profile_interval=xxx

All reports are concatenated into a single file. If used without +vera_profile_range, Vera will report on the memory usage every interval as specified for the entire simulation. If used with +vera_profile_range, vera will report on the memory usage every interval within the specified range. When no physical unit is specified, the value specified is scaled in simulation HDL time units. Optionally, the physical units can be added (ms, us, ns, ps, fs). A warning message will print out if the physical time unit is smaller than the HDL resolution. vera_profile_limit Specifies an optional limit for generating call reports. By default, the profiler tracks 500 function, task and program calls. Functions, tasks and programs called for the first time after the 500 limit is reached are grouped together and a message is placed at the top of the log file indicating the time spent on these functions, tasks and programs. The following example sets the limit to 1,000 calls:
+vera_profile_limit=1000

vera_profile_range Sets the start and stop time for generating memory usage reports. This allows for generation of memory profile reports during a specific time in the simulation. This command must be used in conjunction with +vera_profile_interval. A final end of simulation memory report will also be added to the file.

Compiling and Running Testbenches 3-40

+vera_profile_range=yyy:zzz

If time units are not specified by vera_profile_interval, yyy and zzz are in simulation HDL time units. (see vera_profile_interval on page 3-40). vera_rand48_seed Sets the seed for calls to the rand48() system function. vera_random_seed Sets the seed value used by the top level random number generator at the start of simulation. The random(seed) system function call overrides this setting. vera_region_size Specifies the maximum number of regions within the simulation. The default value is 256. vera_semaphore_size Specifies the maximum number of semaphores within the simulation. The default limit is 2048. vera_solver_cpu_limit Specifies the time limit for issuing a solver timeout. There is no limit by default. This option is supported in all solver modes. See Solver Runtime Options to Control Memory and CPU Usage on page 5-114 for more details.
+vera_solver_cpu_limit=<value>

vera_solver_diagnostics_filename Specifies the name of the file for storing diagnostic information. The file is not created if no diagnostic message is reported. If this option is not specified, the diagnostic information is displayed on standard I/O. See Constraint Solver Diagnostics on page 5-111 for more details.
Compiling and Running Testbenches 3-41

vera_solver_memory_limit Specifies the maximum amount of memory for storing computation information generated by the constraint solver. There is no limit by default. This option is supported by the default solver only. See Solver Runtime Options to Control Memory and CPU Usage on page 5-114 for more details.
+vera_solver_memory_limit=<value>

vera_solver_mode Selects the Vera constraint solver to use. When set to 1, the solver spends more pre-processing time in analyzing the constraints, during the first call to randomize() on each class. Subsequent calls to randomize() on that class are very fast. When set to 2, the solver does minimal pre-processing, and analyzes the constraint in each call to randomize(). vera_udf Allows you to attach multiple Vera UDF libraries:
simv +vera_mload=files.vrl +vera_udf=file1.dl:file2.dl...

For more information on using the vera_udf runtime option, see the Vera:Deprecated Features and Backward Compatibility document. vera_vros Specifies the names of multiple .vro files to be loaded:
simv +vera_vros=fileA.vro,fileB.vro,fileC.vro

The files are contained in a comma-separated list. No white spaces are permitted in the list.

Compiling and Running Testbenches 3-42

Passing Data at Runtime


OpenVera can read HDL plus arguments using the get_plus_arg() system function. The VHDL equivalent to plus arguments is included in the vera.ini file. Syntax
function reg get_plus_arg(CHECK | HNUM | NUM | STR, string plus_arg);

Predefined Macros: The valid values for plus argument requests are:
Request CHECK HNUM Action returns 1 if the specified plus argument is present returns a hexadecimal number attached to the specified plus argument returns an integer attached to the specified plus argument returns a string attached to the specified plus argument (returns a bit string type and not a string primitive type)

NUM

STR

plus_arg Is the plus argument you want to evaluate. The get_plus_arg() system function returns a value based on the request type and plus_arg value. Note: get_plus_arg() can capture only 32-bits of a number from the command line.

Compiling and Running Testbenches 3-43

Example 3-7
#include <vera_defines.vrh> #define DEF_RP_TIMES 10 #define DEF_RSEED 32'habcd_ef01 #define DEF_LOG_FILE_NAME "test.log" program test{ integer repeat_times = DEF_RP_TIMES; reg [31:0] random_seed = DEF_RSEED; reg [2047:0] bit_str; //max 256 char string log_file_name = DEF_LOG_FILE_NAME; // get repeat times if any if ( get_plus_arg ( CHECK, "set_repeat_times=" ) ){ repeat_times = get_plus_arg ( NUM, "set_repeat_times="); } // get random seed if any if ( get_plus_arg ( CHECK, "set_random_seed=" ) ){ random_seed = get_plus_arg ( HNUM, "set_random_seed=" ); } // get log file name if any if ( get_plus_arg ( CHECK, "set_log_file_name=") ){ bit_str = get_plus_arg ( STR, "set_log_file_name=" ); log_file_name.bittostr ( bit_str ); } printf (" repeat times is %0d\n", repeat_times ); printf (" random seed is %h\n", random_seed ); printf (" log file name is %s\n", log_file_name ); }

This example is invoked with this command line:


vera_cs filename.vro +set_repeat_times=7 +set_log_file_name=log.file \ +set_random_seed=3

Compiling and Running Testbenches 3-44

Referencing Variables
Forward reference is allowed with interface signals, port signals, bind signals, global variables, and task and function calls that are present at the top level. Enumerated types, classes, coverage_group, functions, global variables, hdl_tasks and tasks defined in other files require an extern declaration in the file referencing that symbol.

External Declaration of Subroutines


The external declaration of subroutines enables the use of multiple source files (that is, functions and tasks can be declared in separate source files). Large functions and tasks can be compiled separately, which facilitates debugging. You must declare subroutines as external at the top level:
extern task | function subroutine (argument_list);

Alternatively, for ease of use and debugging, a header file can be generated when a source file is compiled with the -HC option (see Compilation Options on page 3-4). The generated header file contains all of the extern statements for that source file. Note: When using external subroutines, the argument types that are passed must match exactly. So take extra care when passing arguments to external subroutines.

Compiling and Running Testbenches 3-45

The default values can be set locally, and independently, for each compilation unit using extern declarations with default values. A general library, which can then be customized for a particular user or testbench, can be implemented by using include files with different defaults. For example, the task write() may be defined in a separate library, which is compiled independently. The Vera file in which the task write() will be used must declare write() as being external. Default values can be set in this extern declaration:
// file A (library) task write (integer i, k, reg[5:0] data) { // write definition } // file B (testbench) extern task write(integer i = 10,integer k,reg[5:0]data=6'b1); task xyz () { write (*, 5); //continue task declaration }

Compiling and Running Testbenches 3-46

4
Vera-SystemC Transaction Level Interface 4
Up until v6.3, Vera supported interaction with SystemC models at the pin level. The methodology introduced here enhances the existing Vera-SystemC interface but does not change the existing flow. With the Vera-SystemC Transaction Level Interface (TLI), Vera can interface with SystemC at the transaction level. Verification is greatly enhanced by bringing Veras constraint randomization and coverage capability into the SystemC environment.

4-1

Overview
The following are the basic steps to enable Vera-SystemC TLI transactions: 1. Start with a SystemC model to be verified. 2. Create an interface configuration (.icf) text file. A predetermined format is used to list the methods of the SystemC model. 3. Use Vera to read the .icf configuration text file to automatically create an infrastructure that enables the TLI. This infrastructure will be in both the Vera and SystemC domain. 4. On the Vera side, the user creates a Vera program file that will instantiate Transaction Object (an instance of the rvm_sc_data class) and Transaction Channel (an instance of the rvm_sc_channel class). Both are part of the infrastructure. Putting a Transaction Object into a Transaction Channel in Vera passes that Transaction Object to SystemC. 5. On the SystemC side, the user will create a SystemC sc_main file that instantiates a top level SystemC class. This class will contain the SystemC model, a clock generator, a Vera shell, and the Transaction Master (which is part of the infrastructure). The Transaction Master will take the Transaction Object from Vera and call a method in the SystemC model (see Figure 4-1).

Vera-SystemC Transaction Level Interface 4-2

Figure 4-1

V raS el e hl

T n a tio ra s c n O je t b c

T n ra s O je t b c (w ) rite tr n a tio c a n l a sc n hn e Tn ra s O je t b c

Ta s rn Ms r a te C c lo k G n ra r e e to

DT U

V ra e

(re d a) tra s c nc a n l n a tio h n e

S s m to y te C p

SystemC Memory Example


What follows is an example that shows how the Vera-SystemC TLI works.

SystemC Memory Model


The SystemC model Mem is a simple memory model of 1000 elements of unsigned int. There are two methods to access the mem, read and write.

Vera-SystemC Transaction Level Interface 4-3

Example 4-1 Mem.h


#include <systemc.h> #include "mem_if.h" #define MEMSIZE 1000 class Mem : public mem_if, public sc_module { unsigned int mem[MEMSIZE]; unsigned int idx; public : Mem(sc_module_name name); void read(unsigned int addr, unsigned int &datao); void write(unsigned int addr, unsigned int datai); };

Example 4-2 Mem.cpp


#include"Mem.h" Mem::Mem(sc_module_name name): sc_module(name), idx(0) {} void Mem::read(unsigned int addr, unsigned int &datao) { if (addr < MEMSIZE) { datao = mem[addr]; } else { cerr << "Error - addr(" << addr << ") //out of bounds [0:" << MEMSIZE-1 <<"]\n"; } } void Mem::write(unsigned int addr, unsigned int datai) { if (addr < MEMSIZE) { mem[addr] = datai; } else { cerr << "Error - addr(" << addr << ") //out of bounds [0:" << MEMSIZE-1 <<"]\n"; } }

Note: mem_if.h (see Example 4-3) is the SystemC interface class from which Mem.h is derived.

Vera-SystemC Transaction Level Interface 4-4

Example 4-3 mem_if.h


class mem_if : public sc_interface { public : virtual void read(unsigned int addr, unsigned int &datao)=0; virtual void write(unsigned int addr, unsigned int datai)=0; };

Interface Configuration File


Based on the template depicted in Example 4-4, the user creates the .icf. This file is needed by Vera to generate the supporting files for the TLI. Information (for example, name of the methods) in the .icf file can be found in mem_if.h.

Example 4-4 Template for developing the .icf file


SC_If_Header_File_Name: Header_file_name Interface_Begin name_of_SystemC_interface_class Template_Map_List_Begin Template_Map_List_End Map_List_Begin Map_List_End Transaction_Begin name_of_method IMC_Arg_List: comma_separated_list_of_arguments Tx_Begin argument_name Data_Type: data_type ArraySize: array_size Tx_End Rx_Begin <arg_name> Data_Type: data_type ArraySize:array_size IsReturnData; Rx_End Transaction_End Interface_End

Vera-SystemC Transaction Level Interface 4-5

Example 4-5 User created mem_if.ucf


SC_If_Header_File_Name: mem_if.h #name of the SystemC interface class Interface_Begin mem_if #name of 1st method is "read" Transaction_Begin read IMC_Arg_List: addr, datao #name of 1st argument for 1st method is "addr" Tx_Begin addr #1st argument type of 1st method is "unsigned int" Data_Type: unsigned int ArraySize: Tx_End # 2nd argument of 1st method is "datao" Rx_Begin datao Data_Type: unsigned int & ArraySize: Rx_End Transaction_End # name of 2nd method is "write" Transaction_Begin write #argument(s) of 2nd method IMC_Arg_List: addr, datai #name of 1st argument for 2nd method is "addr" Tx_Begin addr #1st argument type of 2nd method is "unsigned int" Data_Type: unsigned int ArraySize: Tx_End # 2nd argument of 2nd method is "datai" Tx_Begin datai Data_Type: unsigned int ArraySize: Tx_End Transaction_End Interface_End

Vera-SystemC Transaction Level Interface 4-6

Using Vera to Create the TLI Infrastructure


After creating the mem_if.ucf file, invoke Vera to generate the needed source files for enabling the Vera-SystemC TLI.
% vera -tem -tli_gen -systemc mem_if.ucf

These files are created. TO_mem_if.cpp TO_mem_if.h mem_if_master.cpp mem_if_master.h mem_if_slave.cpp mem_if_slave.h TO_mem_if.vr

The TO_mem_if.cpp and TO_mem_if.h files contain the implementation of the transaction objects such as display, pack. The mem_if_master.cpp and mem_if_master.h files together are the Transaction Master. These files contain the SystemC "wrapper" module that will be used to call the interface methods of the Mem module. In this case the DUT represents a SystemC "slave" that implements the interface 'mem_if'. The TO_mem_if.vr file is the Vera implementation of the Transaction Object.

Vera-SystemC Transaction Level Interface 4-7

Creating the Vera Testbench Program


Vera needs a "main program" to run. This will contain the program construct. To send data from Vera to the SystemC model, the user will instantiate the transaction object and channel classes (declared in the TO_mem_if.vr file listed above) in the main program. The Transaction Object can be, for example, randomized on the Vera side. It is then sent to the SystemC model (Mem) via the Transaction Channel. Here is an example of testbench.vr:

Example 4-6 test.vr


program test { integer i; // these classes are defined in TO_mem_if.vr TO_mem_if_write w_to; TO_mem_if_write_tx_rx_channel_pair w_chan; TO_mem_if_read r_to; TO_mem_if_read_tx_rx_channel_pair r_chan; printf("Start of Vera \n"); // creating transaction objects, w_to = new(); r_to = new(); to be pass to SystemC

// creating transaction channels to pass data from Vera to SystemC r_chan = new("readto_channel", "readto_channel_1"); // these //must match the channels in mem_if_master.h w_chan = new("writeto_channel", "writeto_channel_1"); // write to SystemC mem by putting data (transaction objects) // into the write channel for (i=0; i<10; i++) { // void = w_to.randomize(); // randomize a Trans Obj w_to.addr = i; w_to.datai = i*10; @(posedge CLOCK); w_to.display(); w_chan.tx_put_t(w_to); w_to = w_chan.rx_get_t();

Vera-SystemC Transaction Level Interface 4-8

} repeat(30) @(posedge CLOCK); // read from SystemC mem by putting data (transaction objects) // into the read channel for (i=0; i<10; i++) { r_to.addr = i; @(posedge CLOCK); r_chan.tx_put_t(r_to); r_to = r_chan.rx_get_t(); r_to.display(); } repeat(30) @(posedge CLOCK); printf("End of Vera \n"); }

Create SystemC main Program


The SystemC "main program" instantiates an instance of class top. Class top is the top level class that hooks up mem_if_master, mem_if_slave, Mem, vera_shell, and a clock generator. These are necessary components to enable Vera and the SystemC model to talk to each other. This file is created manually. Example 4-7 is an example of a SystemC main program that instantiates class top.

Example 4-7 main.cpp


#include "systemc.h" #include "top.h" int sc_main(int argc, char **argv) { top top_1("top_1"); //instantiates class "top" sc_start(-1); return 0; }

Example 4-8 is an example of a SystemC class top that hooks up mem_if_master, Mem, vera_shell, and a clock generator. mem_if_slave is omitted from this example.

Vera-SystemC Transaction Level Interface 4-9

Example 4-8 top.h


#ifndef __top_h #define __top_h #include <systemc.h> #include "Mem.h" #include "mem_if_master.h" #include "main_shell.h" class top: public sc_module { public: // must have these module instances mem_if_master *master; // the Vera-SystemC translator Mem *mem; // the SystemC slave model sc_clock *clk; // clock generator main_shell *vera_shell; // Vera shell // default constructor SC_CTOR(top) { // create the schematic master = new mem_if_master("master"); mem = new Mem("bus"); clk = new sc_clock("clk"); vera_shell = new main_shell("vera_shell"," \ +vera_mload=vera_objects.vrl"); master->mem_if_port(*mem); master->clk(*clk); vera_shell->SystemClock(*clk); } }; // end module #endif

Compile and Run


Compile Vera source files
% vera -cmp -HC -I$VERA_HOME/include/rvm_sc TO_mem_if.vr % vera -cmp -HC -I$VERA_HOME/include/rvm_sc main.vr % vera -cmp -systemc -I$VERA_HOME/systemc -I$VERA_HOME/include/ \ rvm_sc main.vr

Once all these components are created, it is time to compile the SystemC source files.

Vera-SystemC Transaction Level Interface 4-10

Compile SystemC source files Solaris


% g++ -g -c -Wno-deprecated $SC_INCL TO_mem_if.cpp % g++ -g -c -Wno-deprecated $SC_INCL mem_if_master.cpp % g++ -g -c -Wno-deprecated $SC_INCL Mem.cpp % g++ -g -c -Wno-deprecated $SC_INCL main.cpp

Link This links SystemC object files into an executable (called mem_testbench). Solaris
% g++ \ -o mem_testbench \ TO_mem_if.o mem_if_master.o Mem.o main.o \ -L${VERA_HOME}/lib/systemc -lVERA -lrvm_sc_osci \ -L${SYSTEMC}/lib-gccsparcOS5 -lsystemc -lsocket -ldl \ -lnsl -lresolv -WI -export-dynamic -uspawn_tattletale_sc2vr

Run
% mem_testbench

Output
SystemC 2.0.1 --- Oct 31 2003 10:33:56 Copyright (c) 1996-2002 by all Contributors ALL RIGHTS RESERVED Registered rvm_sc_channels are: readto_channel_txreadto_channel_1_tx1 Registered rvm_sc_channels are: readto_channel_rxreadto_channel_1_rx1 readto_channel_txreadto_channel_1_tx1 Registered rvm_sc_channels are: readto_channel_rxreadto_channel_1_rx1 readto_channel_txreadto_channel_1_tx1 writeto_channel_txwriteto_channel_1_tx1 Registered rvm_sc_channels are: readto_channel_rxreadto_channel_1_rx1 readto_channel_txreadto_channel_1_tx1

Vera-SystemC Transaction Level Interface 4-11

writeto_channel_rxwriteto_channel_1_rx1 writeto_channel_txwriteto_channel_1_tx1 ++---------------------------------------------------------------++ || VERA System Verifier (TM) || || || || Copyright (c) 1995-2004 by Synopsys, Inc. || || All Rights Reserved || || || || For support, send email to vera-support@synopsys.com || || || || This software and the associated documentation areconfidential|| || and proprietary to Synopsys Inc.Your use or disclosure of this|| || software is subject to the terms and conditions of a written || || license agreement between you or your company and Synopsys,Inc.|| ++---------------------------------------------------------------++ Vera: Loading /<VERA_HOME_INSTALL>/vro/rvm_sc/rvm_sc_lib. vro.. Vera: Loading TO_mem_if.vro.. Vera: Loading main.vro.. Start of Vera VERA - creating channelsVERA - put data into the write channel writing:addr = 0x00000000datai = 0x00000000 CPP - accessing Mem::write writing:addr = 0x00000001datai = 0x0000000a CPP - accessing Mem::write writing:addr = 0x00000002datai = 0x00000014 CPP - accessing Mem::write writing:addr = 0x00000003datai = 0x0000001e CPP - accessing Mem::write writing:addr = 0x00000004datai = 0x00000028 CPP - accessing Mem::write writing:addr = 0x00000005datai = 0x00000032 CPP - accessing Mem::write writing:addr = 0x00000006datai = 0x0000003c CPP - accessing Mem::write writing:addr = 0x00000007datai = 0x00000046 CPP - accessing Mem::write writing:addr = 0x00000008datai = 0x00000050 CPP - accessing Mem::write writing:addr = 0x00000009datai = 0x0000005a CPP - accessing Mem::write VERA - done with put data into the write channel VERA - get data out of the read channel CPP - accessing Mem::read reading:addr = 0x00000000datao = 0x00000000 CPP - accessing Mem::read reading:addr = 0x00000001datao = 0x0000000a CPP - accessing Mem::read reading:addr = 0x00000002datao = 0x00000014 CPP - accessing Mem::read

Vera-SystemC Transaction Level Interface 4-12

5
Randomization in Vera
This chapter covers the following topics: Random Stability Seeding for Randomization Randomization: Hierarchical Seed Saving randcase Statements Random Number Generation Constraint Based Randomization Random Sequence Generation

Randomization in Vera 5-1

Random Stability
Random Number Generation (RNG) is now localized to threads and objects. Because the stream of random values returned by a thread or object is independent of the RNG in other threads or objects, this property is called Random Stability. Random stability applies to the system randomization calls, random() (see page 5-14), urandom() page 5-15, and srandom() (see page 5-7), the object randomization method, randomize() (see page 5-21), randcase (see page 5-12), the vera stream generator language randseq() constructs.

This feature means that Vera programs exhibit more stable RNG behavior in the face of small changes to the user code. Additionally, you can choose to exercise precise control over the generation of random values by manually seeding threads and objects. Compatibility Random stability is enabled by default. The command line option, +vera_disable_random_stability, (see vera_disable_random_stability on page 3-30), disables all of the random stability modes. The overall stream of random values will then be the same as in pre-5.2 versions of Vera. In Vera 6.1, newed objects that do not contain rand or randc members will not take a random value from the parent thread's RNG. This can cause a change in the random data values generated between Vera 6.0 and 6.1. However, only testbenches that compare results to a golden file should be affected.

Randomization in Vera 5-2

Random Stability Properties Random stability encompasses the following properties: Program and thread stability Each thread has an independent RNG source for all randomization system calls invoked from that thread. When a new thread is created, its RNG is seeded with the next random value from its parent thread. This property is called hierarchical seeding. Program and thread repeatability is guaranteed as long as you create threads and generate random numbers in the same order as before. When adding new threads to existing Vera code, they should be added at the end of a code block in order to maintain random number stability of previously created work. Object stability Each class instance ("object) has an independent RNG source for the randomization method in the class. When an object is created using new(), its RNG is seeded with the next random value from the thread that created the object. An independent RNG source is not created for the object if there are no rand/ randc members in the object hierarchy. Object repeatability/stability is guaranteed as long as you create objects, threads and generate random numbers in the same order as before. New objects, threads and random numbers should be created after existing objects are created.

Randomization in Vera 5-3

Manual seeding You can manually seed all RNG sources. Combined with hierarchical seeding, this allows you to define the operation of a subsystem (hierarchy subtree) completely with a single seed at the root thread of the system.

Program and thread stability Random values returned from Vera system calls (for example, random() on page 5-14, urandom() on page 5-15, the randcase Statements on page 5-12, and the Vera Stream Generator (VSG) randseq(){}), are independent of thread execution order. The program fragment below illustrates several properties:
integer x, y, z; fork //set a seed at the start of a thread {srandom(100); x = random();} //set a seed during a thread {y = random(); srandom(200);} //randcase draws a value from the thread RNG {z = random(); randcase(){ ... }} join all

The above example illustrates the following: Thread Locality. The values returned for x, y and z are independent of the order of thread execution. This is an important property because it allows you to develop subsystems that are independent, controllable, and predictable. Hierarchical seeding. When a thread is created, its random state is initialized using the next random value from the parent thread as a seed. The three forked threads are all seeded from the parent thread.

Randomization in Vera 5-4

Note: Each thread is seeded with a unique value, determined solely by its parent. The root of a thread execution subtree determines the random seeding of its children. This allows you to move subtrees, while preserving their behavior by manually seeding their root thread. Object Stability The randomize() method built into every class exhibits object stability (see randomize() on page 5-21). This is the property that calls to randomize() in one instance are independent of calls to randomize() in other instances, and independent of calls to the system randomize functions. Example 5-1
class Foo { rand integer x; } class Bar { rand integer y; } program main { Foo foo = new(); Bar bar = new(); integer z; void = foo.randomize(); // z = random(); void = bar.randomize();

The values returned for foo.x and bar.y are independent of each other The calls to randomize() are independent of the random system calls. If we uncomment the line z = random(); above, there is no change in the values assigned to foo and bar. Each instance has a unique source of random values that can be seeded independently. That random seed is taken from the parent thread when the instance is created.

Randomization in Vera 5-5

Instances can be seeded at any time using the srandom() initstate(), and setstate() system calls with an optional object argument.
class Foo { task new (integer seed) { //set a new seed for this instance srandom(seed, this); } }

Warning: Once an object is created there is no guarantee that the creating thread can change the objects random state before another thread accesses the object. Therefore, it is recommended that objects self-seed within their new() methods rather than externally. Unlike threads, an objects seed may be set from any thread. Modification of object seeding/random stability Manual Seeding Threads may also be seeded using srandom(), initstate(), or setstate(). There is no way for a thread to set the random state of another thread. The srandom() system call in the example initializes the state for the threads RNG state using the seed (see srandom(), initstate(), and setstate() starting on page 5-7). Other System Calls Stability applies to all OpenVera language constructs and functions that generate random values, including the randcase and the VSG, randseq() on page 5-123. Randcase and randseq() use thread stability, even if they are called from functions/tasks inside an object.

Randomization in Vera 5-6

Reseeding A thread may set a new seed at any time during execution.

Seeding for Randomization


srandom() Syntax
task srandom(integer seed,[object obj]);

The srandom() task initializes the current RNG array using the value of the seed. Note: The seed value may not be 0. The optional object argument is used to seed an object instead of the current thread (context). The top level randomizer state is initialized with srandom(1) prior to any randomization calls, including those that occur during initialization. The top-level randomizer state can be initialized with a user-defined value by the +vera_random_seed=value option (see vera_random_seed on page 3-41). The top-level randomizer state is initialized with the specified seed value.

Randomization in Vera 5-7

initstate() The initstate() task allows a user-defined state array, pointed to by the state argument, to be initialized for future use. Syntax
task initstate(integer seed, var VeraRandomState state, [object obj]);

Note: The seed value may not be 0. The initstate() task initializes the state array using the seed and then attaches the state array to the current randomizer using the setstate() semantics below. The optional object argument is used to seed an object instead of the current thread (context). The state array argument must be declared as type VeraRandomState, which is defined in <vera_defines.vrh>. setstate() Syntax
task setstate(var VeraRandomState state, [object obj]);

The setstate() task attaches the state array to the current thread or specified object. The state array will be changed whenever random() or urandom() is called on the current randomizer. The optional object argument is used to seed an object instead of the current thread (context). The state array argument must be declared as type VeraRandomState, which is defined in <vera_defines.vrh>. Any previously attached state is garbage collected.

Randomization in Vera 5-8

The system maintains a reference to the state array until initstate() or setstate() is called again, or until the thread or object is garbage collected. getstate() Syntax
task getstate(var VeraRandomState state,[object obj]);

This call returns a copy of the state values for the current thread or specified object. The state argument must be declared as type VeraRandomState, which is defined in <vera_defines.vrh>. Alternate RNG Options You may use the runtime option +vera_use_system_random, which causes random(), urandom(), initstate(), and setstate() to use the equivalent libC UNIX functions. When this option is enabled, random stability is automatically disabled. Manually Seeding Randomize Each object maintains its own internal random number generator, which is used exclusively by its randomize() method. This allows objects to be randomized independent of each other and calls to the system random functions. When an object is created, its random number generator (RNG) is seeded using the next value from the RNG of the thread that created the object. This process is called hierarchical object seeding.

Randomization in Vera 5-9

Sometimes it is desirable to manually seed an objects RNG using the srandom() system call. This can be done either in a class method, or external to the class definition:
class Packet { rand reg[15:0] header; ... task new (integer seed) { srandom(seed, this); ... } }

or externally:
Packet p = new(200); // Create p with seed 200. srandom(300, p); // Re-seed p with seed 300

Object RNGs can also be controlled using the initstate() and setstate() system calls. Best practice: When used in the new() task, srandom() should be called first, and all the class variables should be initialized following the call to srandom(). This assures the objects RNG is set with the new seed before any class member values are initialized to their default values or any contained objects are created.

Randomization: Hierarchical Seed Saving


The vera_save_rng_state() and vera_restore_rng_state() system tasks control the states of all Random Number Generators that branch from the current thread or object handle reference. Vera can only save the present states or restore them from a previous save, within the same simulation.
Randomization in Vera 5-10

Syntax
task vera_save_rng_state([object]); task vera_restore_rng_state([object]);

When object not specified: When an object is not specified, vera_save_rng_state() saves the state of the current thread and all sub-threads below the current thread and stores it in the current thread. vera_save_rng_state() does not store the state of objects when an object is not specified as an argument. When vera_restore_rng_state() is called, the rng state is restored for all threads stored in the previous vera_save_rng_state() if they exist at the time the call is made. New threads that might have been created are ignored. When object is specified: When an object is specified, vera_save_rng_state() saves the random state for the current object and all contained objects in the current object. When vera_restore_rng_state() is called on that object and restores the random state. In addition, the random state of all threads that have been forked from the objects methods and the methods of its contained objects are saved and restored. New threads that have been created after save are again ignored. If vera_save_rng_state() is called repeatedly on the same object or thread, only the last saved state will be stored.

Randomization in Vera 5-11

Example 5-2
#include <vera_defines.vrh> class C{ rand reg[8:0] v; } program rand_test{ C c = new; vera_save_rng_state(c); void = c.randomize() vera_restore_rng_state(c); void = c.randomize(); }

In the above example, both calls to randomize will produce the same random numbers. The system calls have no effect when random stability is disabled or when random_compat is set. If vera_restore_rng_state() is called on a thread or object that has no previous saved state, a warning is issued.

randcase Statements
The randcase statement specifies a block of statements, one of which is executed randomly. The syntax to declare a randcase block is:
randcase { weight1 : statement1 weight2 : statement2 ... weightN : statementN }

Randomization in Vera 5-12

weight Can be any valid expression, including a constant. The weight expression is evaluated every time a randcase is executed. If weight is zero, that branch will not be used. statement Can be any valid statement or block of statements. If a code block is used, the entire block is executed. When the randcase statement is executed, a statement is randomly selected from the randcase block. Different weights can be used to change the probability that any given statement is selected. The probability that any single statement is selected is determined by weight/total_weight. Note that randcase statements can be nested. Example 5-3 randcase block
randcase { 10: i=1; 20: i=2; 50: i=3; }

Example 5-3 defines a randcase block with the specified weights. There is a .125 probability that the first statement is executed, a .25 probability that the second statement is executed, and a .625 probability that the third statement is executed.

Randomization in Vera 5-13

Random Number Generation


random()
The random() function returns a 31-bit pseudo-random positive integer value from the current thread RNG. Syntax
function integer random([integer seed]);

seed Is an optional argument that determines which random number sequence is generated. The seed can be any valid Vera expression, including variable expressions. The random number generator generates the same number sequence every time the same seed is used. Note: A seed value of 0 is a special case in which the random number sequence is the same as the one generated with a seed value of 1. The random() function takes an optional seed argument that is used to call srandom() (see srandom() on page 5-7) before computing the random value. In this case the system behaves as if srandom(seed) had been called before random(). The random number generator is deterministic. Each time the program executes, it cycles through the same random sequence. You can make this sequence non-deterministic by seeding the random() function with an extrinsic random variable, such as the time of day. Since random() always returns a positive number, the sign bit is 0. Only the 31 least significant bits are random.

Randomization in Vera 5-14

Typically, to generate random numbers, you first call the random() system function with an integer seed value. Then call the random() function without a seed each time you need a new random number. Example 5-4
random( 184984 ); // Initialize the generator addr = {random(),random()}; ph_number = random() >> 5;

The command line argument +vera_random_seed=value can be used to set the seed used by the top level random number generator at the start of simulation. The random(seed) system function call overrides this setting. Example 5-5
program dut_test { printf("First random value = %h\n", random(1)); }

urandom()
The urandom() function returns a 32-bit pseudo-random unsigned bit vector value from the current thread RNG. Syntax
function reg[31:0] urandom([integer seed]);

The urandom() function takes an optional seed argument that is used to call srandom() before computing the random value. Note: The seed value may not be 0.

Randomization in Vera 5-15

In this case the system behaves as if srandom(seed) had been called before urandom().

rand48()
The rand48() function generates an integer (random) number based on the lrand48 algorithm. Syntax
function integer rand48([integer seed]);

Since rand48() always returns a positive number, the sign bit is 0. Only the 31 least significant bits are random. For more information on the lrand48() algorithm, see the Unix man pages (from a Unix shell, type man lrand48). Note: The random() function is recommended over rand48() because it yields a better distribution of random values. Also, rand48() does not adhere to random stability.

urand48()
The urand48() function generates an unsigned 32-bit random number based on the mrand48 algorithm. Syntax
function reg [31:0] urand48([integer seed]);

Note: Also, urand48() does not adhere to random stability

Randomization in Vera 5-16

For more information on the mrand48 algorithm, see the Unix man pages (from a Unix shell, type man mrand48).

urandom_range()
Syntax
function reg[31:0] urandom_range(reg[31:0] maxval[, reg[31:0] minval=0]);

The function returns an unsigned value in the range maxval..minval. Example 5-6
val=urandom_range(7,0);

If the minval argument is omitted, the function returns a value in the range maxval..0. Example 5-7
val=urandom_range(7);

If maxval is less than minval, the arguments are automatically reversed so that the first argument is larger than the second argument. This swap is done rather than issuing a runtime exception. Example 5-8
val=urandom_range(0,7);

All of these examples produce values in the range of 0 to 7.

Randomization in Vera 5-17

random_range()
Syntax
integer random_range(integer maxval [,integer minval]);

The function returns an integer in the range maxval..minval. Example 5-9


val=random_range(7,-7);

If the minval argument is omitted, the function returns an integer in the range maxval..0. Example 5-10
val=urandom_range(7);

If minval is greater than maxval, then a warning is issued and the range is automatically reversed.

rand_normal()
rand_normal() returns an integer with normal (Gaussian) distribution. Syntax
integer rand_normal(integer mean, integer sd);

Where sd is the standard deviation.

Randomization in Vera 5-18

rand_poisson()
rand_poisson() returns an integer with poisson distribution. Syntax
integer rand_poisson(integer mean);

If the mean does not have a positive value a warning is issued and 0 is returned.

rand_t()
rand_t() returns an integer with t distribution. Syntax
integer rand_t(integer df);

Where df is the degrees of freedom If the degrees of freedom argument does not have a positive value a warning is issued and 0 is returned.

rand_exponential()
rand_exponential() returns an integer with exponential distribution. Syntax
integer rand_exponential(integer mean);

If the mean does not have a positive value a warning is issued and 0 is returned.

Randomization in Vera 5-19

rand_erlang()
rand_erlang() returns an integer with erlang distribution. Syntax
integer rand_erlang(integer k, integer mean);

Where k is the number of stages. If k does not have a positive value a warning is issued and 0 is returned.

rand_chi_square()
rand_chi_square() returns an integer with chi square distribution. Syntax
integer rand_chi_square(integer df);

Where df is the degrees of freedom If the degrees of freedom argument does not have a positive value a warning is issued and 0 is returned.

Randomization in Vera 5-20

Constraint Based Randomization


This section introduces basic concepts and uses for generating random stimulus within objects. The OpenVera language uses an object-oriented method for assigning random values to the member variables of an object subject to user-defined constraints. Example 5-11
class Bus{ rand reg[15:0] addr; rand reg[31:0] data; constraint word_align {addr[1:0] == 2b0;} }

The Bus class models a simplified bus with two random variables: addr and data, representing the address and data values on a bus. The word_align constraint declares that the random values for addr must be such that addr is word-aligned (the low-order 2 bits are 0). randomize() The randomize() method (see page 5-88 for syntax) is called to generate new random values for a bus object:
program test{ Bus bus = new; repeat (50){ integer result = bus.randomize(); if (result == OK) printf("addr = %16h data = %32h\n", bus.addr, bus.data); else printf("Randomization failed.\n"); } }

Randomization in Vera 5-21

New values are selected for all of the random variables in an object such that all of the constraints are true (satisfied). In the program test above, a bus object is created and then randomized 50 times. The result of each randomization is checked for success. If the randomization succeeds, the new random values for addr and data are printed; if the randomization fails, an error message is printed. In this example, only the addr value is constrained, while the data value is unconstrained. Unconstrained variables are assigned any value in their declared range. Constraint programming is a powerful method that lets you build generic, reusable objects that can later be extended or constrained to perform specific functions. The approach differs from traditional procedural and object-oriented programming, as illustrated in this example that extends the Bus class: Example 5-12
enum AddrType = low, mid, high; class MyBus extends Bus{ rand AddrType type; constraint (type (type (type } } addr_range{ == low ) => addr in { 0 : 15}; == mid ) => addr in { 16 : 127}; == high) => addr in {128 : 255};

The MyBus class inherits all of the random variables and constraints of the Bus class, and adds a random variable called type that is used to control the address range using another constraint. The addr_range constraint uses implication to select one of three range constraints depending on the random value of type. When a MyBus object is randomized, values for addr, data, and type are computed such that all of the constraints are satisfied. Using

Randomization in Vera 5-22

inheritance to build layered constraint systems allows you to develop general-purpose models that can be constrained to perform application-specific functions. Objects can be further constrained using the randomize() with construct (see Inline Constraints Using "randomize() with" on page 5-94) which declares additional constraints inline with the call to randomize(): Example 5-13
task exercise_bus (MyBus bus) { integer res; // EXAMPLE 1: restrict to small addresses res = bus.randomize() with {type == small;} ; ... // EXAMPLE 2: // restrict to address between 10 and 20 res = bus.randomize() with {10 <= addr && addr <= 20;}; ... // EXAMPLE 3: // restrict data values to powers-of-two res = bus.randomize() with {data & (data - 1) == 0;}; ... }

This example illustrates several important properties of constraints: Constraints can be any OpenVera expression with variables and constants of type reg, integer, or enumerated type. Constraint expressions follow Verilog syntax and semantics, including precedence, associativity, sign extension, truncation, and wrap-around.

Randomization in Vera 5-23

The Vera constraint solver is very general and can handle a wide spectrum of seemingly hard problems, including algebraic factoring, complex Boolean expressions, and mixed integer and reg expressions. In the example above, the power-of-two constraint was expressed arithmetically. It could have also been expressed using a shift operator. For example, 1 << n, where n is a 5-bit random variable. The Vera constraint solver is robust. If a solution exists, the solver will find it. The solver only fails when the problem is over-constrained and there is no combination of random values that satisfy the constraints. Constraints interact bidirectionally. In this example, the value chosen for addr depends on type and how it is constrained, and the value chosen for type depends on addr and how it is constrained. It is important to understand that Vera treats all expression operators bidirectionally, including the implication operator (=>).

Sometimes it is desirable to disable constraints on random variables. For example, consider the case where we want to deliberately generate an illegal address (non-word aligned):

Randomization in Vera 5-24

Example 5-14
task exercise_illegal(MyBus bus, integer cycles) { integer res; // Disable word alignment constraint. res = bus.constraint_mode(OFF, "word_align"); if (res != OK) printf("constraint_mode(OFF) failed\n"); repeat (cycles) { // CASE 1: restrict to small addresses. res = bus.randomize() with {addr[0] || addr[1];}; ... } // Re-enable word alignment constraint. res = bus.constraint_mode(ON, "word_align"); if (res != OK) printf("constraint_mode(ON) failed\n"); }

The constraint_mode() method (see page 5-101) can be used to enable or disable any named constraint block in an object. In this example, the word-alignment constraint is disabled, and the object is then randomized with additional constraints forcing the low-order address bits to be non-zero (and thus unaligned). Best practice: Design your constraint hierarchy such that the lowest-level constraints represent physical limits. These limits should be grouped by common properties into well-named constraint blocks that can be independently enabled or disabled. Similarly, the rand_mode() method (see page 5-98) can be used to enable or disable any random variable. When a random variable is disabled, it behaves in exactly the same way as other non-random variables.

Randomization in Vera 5-25

Occasionally, it is desirable to perform operations immediately before or after randomization. Vera provides two built-in methods, pre_randomize() and post_randomize(). These methods are automatically called before and after randomization. These methods can be overloaded with the desired functionality: Example 5-15
class XYPair { rand integer x, y; } class MyYXPair extends XYPair { task pre_randomize() { super.pre_randomize(); printf("Before randomize x=%0d, y=%0d\n", x, y); } task post_randomize() { super.post_randomize(); printf("After randomize x=%0d, y=%0d\n", x, y); } }

By default, pre_randomize() and post_randomize() (see pre_randomize() and post_randomize() on page 5-96) call their overloaded superclass methods. If you overload pre_randomize() or post_randomize(), you should invoke the superclass methods, except when the class is a base class (has no superclass). The random stimulus generation capabilities described here can be combined with the random sequence generation and coverage features to build comprehensive verification environments as well as reusable models. With Veras object-oriented and constraint-based verification technology, you can rapidly develop tests that cover complex functionality and better assure design correctness.

Randomization in Vera 5-26

Random Variables
Class variables can be declared random using the rand and randc type-modifier keywords. Syntax
rand variable; randc variable;

Vera can randomize scalar variables of type integer, reg, and enumerated type. reg variables can be any size. Arrays can be declared rand or randc, in which case all of their member elements are treated as rand or randc. Associative arrays, dynamic arrays and SmartQs can be declared rand or randc. An object variable can be declared rand in which case all of that objects variables and constraints are solved concurrently with the other class variables and constraints. Objects cannot be declared randc. In the case of associative or dynamic arrays, if there is no element in the size range, then a null object references are created and stored for the element.

array_name.size() The special function call array_name.size() is used to refer to the size of an array inside a constraint. It is similar to a function call because it can be used as if it were a 32 bit unsigned variable reporting the size of the array. However, it has the bidirectional ability to limit the size of an array depending on how it is used inside the constraint.

Randomization in Vera 5-27

Syntax
array_name.size() constraint

array_name Is the name of the array or SmartQ. Example 5-16


array_name.size() <= 10;

Note that array_name.size() is treated in Vera as a 32 bit unsigned variable. By Verilog rules, an expression involving signed and unsigned quantities requires that the signed quantities be cast to unsigned values before the expression is evaluated. Therefore,
array_name.size() >= -1;

is recast before evaluation as:


array_name.size() >= 32'hffffffff;

This can cause unexpected results, so be careful not to mix signed and unsigned values. The function array_name.size() operates bi-directionally. If the array is fixed-sized or is non-random, array_name.size(), it generates a constant value that can be used to constrain other variables in the array. If the array is specified as rand, array_name.size() can take the place of (or be an additional constraint to) assoc_size and dynamic_size for setting limits on the size of the randomized array.

Randomization in Vera 5-28

Example 5-17
class GroupLine { rand integer x; rand integer a[] assoc_size x; constraint c { x >=0 ; x <= 5; } }

is equivalent to:
class GroupLine { rand integer a[]; constraint c { a.size() >=0 ; a.size() <= 5; } }

array_name.size() can also set the size or resize randomizeable SmartQs. Best practice: Use array_name.size() instead of assoc_size and dynamic_size. size() in constraints is not completely equivalent to .size() outside constraints. When a random array or queue is resized using randomization, it's size can only increase. It cannot decrease. This is not true outside constraints the size of arrays and queues can be decreased. Only the elements in the numeric key range of 0 to n-1 are randomized, where n is declared using the optional assoc_size keyword.

Randomization in Vera 5-29

Example 5-18
rand reg[7:0] len; rand integer data[] assoc_size len;

The variable len is declared as 8 bits wide. The randomizer computes a random value for the len variable in the 8-bit range of 0 to 255, and then randomizes the first len elements of the data array. If an element does not exist, it is created. If assoc_size is not specified, then randomize() will randomize all of the values in the associative array, but it will not create any new values in the array. The length can be constrained using the optional dynamic_size keyword. The behavior is very similar to that of associative arrays. The exception is that, since dynamic arrays have to represent a set of contiguous indices, the array is resized to the new size, if the new size if more than the current size. In the event that the array is resized, the old values stored in relevant indices are copied over to the new array. Best practice: The old-style use of assoc_size to create a variable-length vector is discouraged because it is inefficient. Instead, use Vera dynamic arrays to model variable length vectors.

rand Modifier Variables declared with the rand keyword are standard random variables. Their values are uniformly distributed over their range. Example 5-19
rand reg[7:0] x;

Randomization in Vera 5-30

This is an 8-bit unsigned integer with a range of 0 to 255. If unconstrained, this variable will be assigned any value in the range 0 to 255 with equal probability. In this example, the probability of the same value repeating on successive calls to randomize is 1/256. randc Modifier Variables declared with the randc keyword are random-cyclic variables that cycle through all the values in a random permutation of their declared range. Random-cyclic variables can only be reg or enumerated types, and are limited to a maximum size of 16 bits, so the maximum range for any randc variable is 0 to 65535. To understand randc, consider a 2-bit random variable y, Example 5-20
randc reg[1:0] y;

which can take on the values 0, 1, 2, and 3 (range 0 to 3). Randomize computes an initial random permutation of the range values of y, and then returns those values in order on successive calls. After it returns the last element of a permutation, it repeats the process by computing a new random permutation.

initial permutation: next permutation: next permutation:

0 2 2

3 1 0

2 3 1

1 0 3

Randomization in Vera 5-31

The basic idea is that randc randomly iterates over all the values in the range and that no value is repeated within an iteration. When the iteration is finished, a new iteration is automatically started. The permutation sequence for any given randc variable is recomputed whenever the constraints change on that variable, or when none of the remaining values in the permutation can satisfy the constraints. The randc variables are solved for first, using only constraints that involve one randc variable and other non-random variables. The values obtained for the randc variables are used as constants while solving for the remaining random variables. Example 5-21
randc reg[3:0] x,y; rand integer z; constraint C { x < 10; y > 5; z == x+y; }

Here x will get a value between 0 and 9 and y will get a value between 6 and 15. These values will be chosen to cycle over values in these ranges, over successive calls to randomize(). The values obtained will be used to solve for z.

Randomization in Vera 5-32

Constraint Blocks
The values of random variables are determined using constraint expressions that are declared using constraint blocks. Constraint blocks are class members, like tasks, functions, and variables. They must be defined after the variable declarations in the class, and before the task and function declarations in the class. Constraint block names must be unique within a class. Syntax
constraint constraint_name {contraint_expressions}

constraint_name Is the name of the constraint block. This name can be used to enable or disable a constraint using the built-in constraint_mode() method. constraint_expressions Are a list of expression statements that restrict the range of a variable or define relations between variables. A constraint expression can be any OpenVera expression, or can use the constraint-specific set operators: in, !in, and dist. The declarative nature of constraints requires the following restrictions on constraint expressions: You cannot call a task or function Operators with side effects, such as ++ and -- are not allowed. Dist expressions cannot appear in other expressions (unlike in and !in).

Randomization in Vera 5-33

Port variables are not allowed in constraint expressions. This is because the width of port-bind variables is not known at compile time.

External Constraint Blocks


Vera allows you to declare external constraint block bodies in the same way you can declare external task and function bodies: Example 5-22
// class declaration class XYPair { rand integer x, y; constraint c; } // external constraint body declaration constraint XYPair::c { x < y; }

Unlike external task and function bodies, external constraint bodies may be declared in any file. There is no requirement that external constraint bodies have to be in the same file as the class definition. External constraint blocks cannot be multiply defined. A loader error will result if a constraint block is declared in more than one .vro file.

Inheritance
Constraints follow the same general rules for inheritance as class variables, tasks, and functions: When you declare a constraint block in an extended class using the same name as a constraint in the base class, the extended class definition overrides the base class definition. For example,
class A{ rand integer x;

Randomization in Vera 5-34

constraint c { x < 0; } } class B extends A{ constraint c { x > 0; } }

An instance of class A constrains x to be less than zero whereas an instance of class B constrains x to be greater than zero. The extended class B overrides the definition of constraint c. Note: constraints are treated the same as virtual functions, so casting an instance of B to an A does not change the constraint set. The built-in randomize() task is virtual, and accordingly, it treats the class constraints in a virtual manner. When a named constraint is overloaded, the previous definition is overridden.

Set Membership
Constraints support integer value sets and set membership operators. The syntax to define a set expression is:
expression set_operator {value_range_list};

expression Can be any OpenVera expression. set_operator Can be in or !in. The in operator returns true if the expression is contained in the set; otherwise it returns false. The !in operator returns the negated value of the in operator. For example, x !in { } is the same as ! ( x in { } ).

Randomization in Vera 5-35

In the absence of any other constraints, all values (either single values or values within ranges), have an equal probability of being chosen by the in or !in operators. value_range_list Is a comma-separated list of integers, enumerated types, reg expressions, and ranges. Ranges are defined by specifying a low and high bound, separated by a colon (low_bound : high_bound). Ranges include all of the integer elements between the bounds. The bound to the left of the colon MUST be less than or equal to the bound to the right, otherwise the range is NULL and contains no values. The bound on the right (high_bound), can be set to $, which represents the largest possible value the expression can take. Example 5-23
rand integer x, y, z; rand reg[3:0] w; constraint c1 {x in {3, 5, 9:15, 24:32, y:2*y, z};} constraint c2 {w in {5:$};} //This is equivalent to {5:15}

Example 5-24
rand integer a, b, c; constraint c3 {a in {b, c};}

Set values and ranges can be any OpenVera expression. Values can be repeated; values and ranges can overlap. It is important to note that the in and !in operators are bidirectional, so the second example is equivalent to a == b || a == c.

Distributions
In addition to set membership, constraints support sets of weighted values called distributions. Distributions have two properties: they are a relational test for set membership, and they specify a statistical distribution function for the results.
Randomization in Vera 5-36

The syntax to define a distribution expression is:


expression dist_operator {value_range_ratio_list};

expression Can be any OpenVera expression that refers to at least one variable declared as rand. dist_operator: Is dist. The dist operator returns true if the expression is contained in the set; otherwise it returns false. In the absence any other constraints, the probability that the expression matches any value is proportional to its specified weight. Dist expressions can only be top-level expressions. value_range_ratio_list Is a comma-separated list of integer, enumerated type, reg expressions, and ranges (the same as the value_range_list for set membership). Optionally, each term in the list has a weight, which is specified using the := or :/ operators. If no weight is specified, the default weight is 1. The weights may be any OpenVera expression. The := operator assigns the specified weight to the item, or if the item is a range, to every value in the range. The :/ operator assigns the specified weight to the item, or if the item is a range, to the range as a whole. If there are n values in the range, the weight of each value is range_weight/n. Example 5-25
x dist {100 := 1, 200 := 2, 300 := 5}

Randomization in Vera 5-37

means x is equal to 100, 200, or 300 with weighted ratio of 1-2-5. If we add an additional constraint that x cannot be 200,
x != 200; x dist {100 := 1, 200 := 2, 300 := 5}

then x is equal to 100 or 300 with weighted ratio of 1-5. It is easier to think about mixing ratios, such as 1-2-5, than the actual probabilities because mixing ratios do not have to be normalized to 100%. It is also easy to convert probabilities to mixing ratios. When weights are applied to ranges, they can be applied to each value in the range, or they can be applied to the range as a whole. Example 5-26
x dist {100:102 := 1, 200 := 2, 300 := 5}

means x is equal to 100, 101, 102, 200, or 300 with a weighted ratio of 1-1-1-2-5.
x dist {100:102 :/ 1, 200 := 2, 300 := 5}

means x is equal to one of 100, 101, 102, 200, or 300 with a weighted ratio of 1/3-1/3-1/3-2-5. In general, distributions guarantee two properties: set membership and monotonic weighting, which means that increasing a weight will increase the likelihood of choosing those values.

Randomization in Vera 5-38

Conditional Constraints
OpenVera provides two constructs for declaring conditional (predicated) constraints: implication and if-else. Implication. The implication operator () can be used to declare an expression that implies a constraint. The syntax to define an implication constraint is:
expression => constraint; expression => constraint_set

expression Can be any OpenVera expression. => The implication operator is =>. The implication operator returns true if the expression is false or the constraint is satisfied; otherwise it returns false. constraint Any valid constraint. constraint_set Is an unnamed constraint block. If the expression is true, all of the constraints in the constraint set must be satisfied.
{ constraint1; constraint2; constarint3; ... constraintN; }

Randomization in Vera 5-39

Example 5-27
mode == small => len < 10; mode == large => len > 100;

In this example, the value of mode implies that the value of len is less than 10 or greater than 100. If mode is neither small nor large, the value of len is unconstrained. The boolean equivalent of (a => b) is (!a || b). Implication is a bidirectional operator. Consider the following example:
reg[3:0] a, b; constraint c {(a == 0) => (b == 1);}

Both a and b are 4 bits, so there are 256 combinations of a and b. The constraint c says that a == 0 implies b == 1, so we have to eliminate 15 combinations: {0,0}, {0,2}, {0,15}. The probability that a == 0 is 1/(256-15) or 1/241. It is important to understand that Vera is designed to cover the whole random value space with uniform probability. This allows randomization to better explore the whole design space than in cases where certain value combinations are preferred over others. if-else Constraints. OpenVera also supports if-else style constraint declarations. Syntax
if (expression) constraint; [else constraint;] if (expression) constraint_set [else constraint_set]

expression Can be any OpenVera expression

Randomization in Vera 5-40

constraint Is any valid constraint. If the expression is true, the first constraint must be satisfied; otherwise the optional else-constraint must be satisfied. constraint_set Is a set of semi-colon separated constraints. If the expression is true, all of the constraints in the first constraint set must be satisfied, otherwise all of the constraints in the optional else-constraint-block must be satisfied.
{ constraint1; constraint2; constarint3; ... constraintN; }

If-else style constraint declarations are equivalent to implications:


if (mode == small) len < 10; else if (mode == large) len > 100;

is equivalent to
mode == small => len < 10; mode == large => len > 100;

In this example, the value of mode implies that the value of len is less than 10, greater than 100, or unconstrained. Just as implication constraints are bidirectional, so are the if-else style constraints.

Randomization in Vera 5-41

Hierarchical Constraints
When an object member of a class is declared rand, all of its constraints and random variables are randomized simultaneously along with the other class variables and constraints. Constraint expressions involving random variables from other objects are called hierarchical constraints. Example 5-28
class A{ rand } class B{ rand rand rand reg[7:0] x;

A left; A right; reg[7:0] x;

constraint C {left.x <= x; x <= right.x;} }

B .left A .x

.x .right A .x

Randomization in Vera 5-42

In Example 5-28, we use hierarchical constraints to define the legal values of an ordered binary tree called a heap. Class A represents a leaf-node with an 8-bit value x. Class B extends class A and represents a heap-node with value x, a left sub-tree, and a right sub-tree. Both sub-trees are declared as rand because we want to randomize them at the same time we randomize the other class variables. The constraint block named C has two hierarchical constraints relating the left and right sub-tree values to the heap-node value. When an instance of class B is randomized, Vera simultaneously solves for B and its left and right children, which in turn may be leaf nodes or more heap-nodes. In this example, Vera solves five heap-nodes simultaneously, assuring that each heap-node meets the left-right ordering requirement. In general, Vera determines which objects, variables, and constraints are to be randomized as follows: 1. Vera first determines the set of objects that are to be randomized as a whole. Starting with the object that invoked the randomize() method, Vera adds all of the objects that are contained within it, are declared rand, and are active (see rand_mode() on page 5-98). The definition is recursive and includes all of the active random objects that can be reached from the starting object. The objects selected in this step are referred to as the active random objects. 2. Global randomization next selects all of the active constraints from the set of active random objects. These are the constraints that are applied to the problem. 3. Global randomization finally selects all of the active random variables from the set of active random objects. These are the variables that are randomized. All other variable references are treated as state variables, whose current value is used as a constant.
Randomization in Vera 5-43

Array Constraints
Array constraints allow specification of templetized constraints that will be elaborated by the solver. We currently support two flavors for array constraints viz. foreach loops and array aggregates/ containment operators. foreach loops. The foreach construct allows constraints to be applied to each member of an array or SmartQ. In a constraint_set, all array types are supported, including fixed size, multi dimensional, associative and dynamic arrays. The foreach construct applies the contained constraints to every indexable member in the array. Syntax
foreach(name, [loop_variable ...constraint_set... } | loop_variable_list]){

name Is the name of the array or SmartQ. loop_variable Is the name of the index variable that is generated automatically and acts as an indexing member. It only needs to be declared in the argument list of the foreach block and has the scope of that block. loop_variable_list Is a comma-separated list of loop variables. An asterisk, *, can be used as a placeholder for an index in a multidimensional array. That index is ignored in the foreach loop.

Randomization in Vera 5-44

constraint_set Can be any valid code for constraints. Example 5-29 Simple foreach loop on a smart Q
class D{ rand integer my_q[$]; constraint init { /* Constrains every member of the queue to be equal to zero */. foreach(my_q,i){ my_q[i] == 0; } } }

Example 5-30 Foreach loop on a two dimensional array


class A{ rand integer d[2][2]; foreach(d, *, index) { (d[0][index] > 22) && (d[0][index] < 33); } }

Example 5-31 Use of guards for constraining two dimensional array, integer d[2][2]
/* Implication operator used to apply constraints to each member of the array. The first member of the array is unconstrained.*/ class C{ rand integer size; rand integer arr[*]; constraint cc{ size > 0; size < 5; foreach (arr, index){ (index > 0 ) => (arr[index] == 0 ); } } }

Randomization in Vera 5-45

Example 5-32 Applying constraints to specific ranges in an array


class D { rand integer arr[*] dynamic_size 30; constraint cc { arr.size() == 30; foreach (arr, index) { (index < 10 ) => { arr[index] > 0; arr[index] < 10;} (index > 9 && index < 20 ) => {arr[index]> 20; arr[index] < 30;} (index > 19 && index < 30) => {arr[index] > 30; arr[index] < 40;} } } }

Example 5-33 Two foreach loops


class E { rand rand integer x[]; integer y[*];

constraint size_cons { x.size() == 10; y.size() == 10; foreach (x, index) { x[index] > 0; x[index] < y[index]; } foreach (y, index) { y[index] > 0; y[index] < 100; } } }

Randomization in Vera 5-46

Example 5-34 Nested foreach


class MyClass { rand integer a[$]; constraint c0 { a.size() >= 10; a.size() != 15; a.size() <= 20; foreach(a , i) { a[i] in {0:1000}; foreach(a , j) { (i != j ) => } } } }

a[i] != a[j];

program ConstraintTest{ MyClass c0 = new(); void = c0.randomize(); foreach(c0.a, index) { printf("a[%0d]: %0d\n",index, c0.a[index]); } }

In the nested foreach example the nested foreach loops are used to constrain elements of an integer array such that all elements of the array are unique. A further constraint is applied limiting the values of each element between 0 and 1000. Example results:
a[0]: a[1]: a[2]: a[3]: a[4]: a[5]: a[6]: a[7]: a[8]: a[9]: 833 425 788 336 304 352 509 434 779 339

Randomization in Vera 5-47

Note on elaboration guards inside foreach loops Constraints residing within the scope of a foreach block can optionally be guarded using a top level implication (=>) operator. If such a guard is specified for a foreach constraint and if that guard comprises of only state variables or random variables whose rand mode is OFF, then the solver will evaluate the guard before any error checking is performed. If such a guard evaluates to FALSE, then the solver will not generate a verification error for the following conditions. x/z values on state variables Null pointer errors Out of bounds array index errors

Consider the following OpenVera example.


class problem{ rand integer buf[5]; constraint out_of_bounds{ // When i = 4, buf[i+1] = buf[5] is // an out of bounds array index foreach(buf,i){ buf[i] == buf[i+1]; } } } program run_time_error{ problem p = new; void = p.randomize(); }

The solver will generate the following error for this example
Constraint solver failed - Constrained entry in rand array is outside of the size. ERROR: Vera Runtime : Fatal Error Location: CALL in program run_time_error (bounds.vr, line 17, cycle 0); READY in function problem.randomize (bounds.vr, line 12, cycle 0)

Randomization in Vera 5-48

Consider a minor variation of the same example, where the foreach constraint is guarded by an appropriate expression.
class problem{ rand integer buf[5]; constraint guarded{ // When i<4, buf[i+1]are valid array // indices foreach(buf,i){ (i < 4) => buf[i] == buf[i+1]; } } } program no_run_time_error{ problem p = new; void = p.randomize(); }

In this case, the solver will not generate a verification error, as buf[i+1] is appropriately guarded. Array Aggregates in Constraints . OpenVera includes a set of aggregate operators which allow declarations of complex constraints for arrays and SmartQs in a compact and flexible format. The following is the syntax for specifying constraints using aggregate operators: The following is the syntax for specifying constraints using sum, product, logical_and, logical_or, bit_and, bit_or, bit_xor, bit_xnor aggregate operators: Syntax
array_name.aggregate_operator() [with loop_variable |loop_variable_list: (loop_expression)]

array_name Is the name of the array or SmartQ.

Randomization in Vera 5-49

aggregate_operator Is any one of the following: sum, product, logical_and, logical_or, bit_and, bit_or, bit_xor and bit_xnor. Detailed descriptions are in the next section. loop_variable Is the variable used to loop through the array or SmartQ. loop_variable_list Is a list of loop variables. A loop_variable_list is only used with multi-dimensional arrays. The syntax for a loop_variable_list is:
* | loop_variable, * | loop_variable...

asterisk * Is the place holder for an index of one of the dimensions. The actual index can be specified in the loop_expression. loop_variable_list - cannot contain only the star, *, which is a placeholder - the number of loop_variables and stars together must match the number of dimensions in the multi-dimensional array. - loop_variables and stars can occur in any order: For example:
loop_var1, *, *, loop_var2 or *, *, loop_var1, loop_var2 // four dimensional array

loop_expression Any valid OpenVera expression. The array aggregate expression is a valid part of a constraint expression and can be used any place that a variable can be used, with the exception of solve-before constraints.
Randomization in Vera 5-50

Example 5-35
x+(arr.sum() with i:(arr[i]+1)) == 10;

contains The following is the syntax for specifying constraints using the contains aggregate operator. Syntax
array_name.contains(contains_expression) [with loop_variable |loop_variable_list: (loop_expression)]

contains_expression Is any valid OpenVera Expression. For definitions of the other syntactic components, see page 5-49. The array aggregate expression is a valid part of a constraint expression and can be used any place that a variable can be used, with the exception of solve-before constraints. Example 5-36
x+arr.contains(1) == 10;

Example 5-37
(arr.contains(x+y) with i:(arr[i]*2)) || (p < q);

Expressions Generated From Aggregate Operator Expressions When an aggregate operator is specified, an expression is generated and expanded into a constraint which is then solved for. The generated expression is a result of applying the operator -except contains -- to each element of the array or SmartQ.
arr[0] operator arr[1] operator arr[2] ...

Randomization in Vera 5-51

If, for example, operator is sum, and the size of the array or SmartQ is three, then the generated expression is:
arr[0] + arr[1] + arr[2]

When the loop_expression is specified using with, the generated expression is the result of applying the operator to a list of expressions that are created from applying each array or SmartQ element to the loop_expression. For example:
arr.sum() with i: (arr[i] + i)

the generated expression is:


( (arr[0] + 0) + (arr[1] + 1) + (arr[2] + 2) )

The aggregate operator, contains, generates a set membership expression and expands it into a constraint which is then solved for. The set membership expression is a result of using the contains_expression as the set expression and each element of the array or SmartQ as the value_range_list.
contains_expression in { arr[0], arr[1], arr[2], ... }

When the optional loop_expression is specified using with, the set membership expression is a result of using the contains_expression as the set expression and each element of the array or SmartQ applying to the loop_expression as the value_range_list.
contains_expression in { loop_exp(arr[0]), loop_exp(arr[1]), loop_exp(arr[2]), ... }

Randomization in Vera 5-52

List of Aggregate Operators Table 5-1


Operator
sum product logical_and logical_or bitwise_and bitwise_or bitwise_xor bitwise_xnor contains

Description
performs addition performs multiplication performs logical AND operation performs logical OR operation performs bitwise AND operation performs bitwise OR operation performs bitwise exclusive OR operation performs bitwise exclusive NOR operation creates a set membership

Example 5-38
class C { rand integer size; rand integer arr[*] dynamic_size size; constraint cc { size == 3; arr.sum() < 100; } }

In Example 5-38, the constraint expression generated is:


arr[0] + arr[1] + arr[2] < 100;

Example 5-39
class C { rand integer size; rand integer arr[*] dynamic_size size; constraint cc { size == 3; arr.sum() with i: (arr[i]+i) < 100; } }

Randomization in Vera 5-53

In Example 5-39, the constraint expression generated is:


((arr[0] + 0) + (arr[1] + 1) + (arr[2] + 2) ) < 100;

Example 5-40 Multi-dimensional arrays


class C { rand integer arr[2][2]; constraint cc { arr.sum() with i, j: (arr[i][j]) < 100; } }

In Example 5-40, the constraint expression generated is:


( arr[0][0] + arr[0][1] + arr[0][2] + arr[1][0] + arr[1][1] + arr[1][2] + arr[2][0] + arr[2][1] + arr[2][2] ) < 100

Example 5-41 Nested aggregates


class D { rand integer x[*]; } class C { rand D arr[*]; constraint cc { foreach(arr, i) { arr[i].x.sum() with j: (arr[i].x[j]) < 100; } } }

Example 5-42 Contains operator


class C { rand integer x; rand integer arr[3]; constraint cc { arr.contains(x) with i: (arr[i]); } }

In Example 5-42, the constraint expression generated is:


x in { arr[0],arr[1],arr[2]};

Randomization in Vera 5-54

Example 5-43 Multi-dimensional array


class C { rand bit[15:0] x[3][3][3]; constraint aggr { x.contains(253) with i,j,*: (x[j][i][0]); } }

In Example 5-43, constraint expression generated is:


253 in {x[0][0][0], x[0][1][0], x[0][2][0], x[1][0][0], x[1][1][0], x[1][2][0], x[2][0][0], x[2][1][0], x[2][2][0]}

Note: When "*" is specified as a placeholder for a particular dimension in the context of array aggregates/containment, that particular dimension is skipped for elaboration. Notes 1. Empty array - If the array over which the aggregate operation is defined has size 0, then the behavior is as follows: - array.sum(): The expression is substituted by 0. - array.product(): The expression is substituted by 1. - array.contains(): The expression is substituted by 0. - For all other aggregate operations there is a runtime error if reference to the aggregate operation is in an ON constraint block. 2. Array types - The array aggregate operators and the foreach loop support the fixed size array, dynamic array, associative array, and SmartQ types of arrays in every context.

Randomization in Vera 5-55

Note on elaboration guards inside array aggregates/ containment operators Aggregates/Containment operators are applied over the expressions that are optionally specified using associated with construct. Furthermore, such expressions can optionally be guarded by using a ternary operator. If such a ternary operator is specified and the predicate expression of that ternary comprises of only state variables or random variables whose rand mode is OFF, then the solver will evaluate the predicate before any error checking is performed. The solver will choose expression specified in the true (false) branch, if the predicate evaluates to true (false) and apply specified aggregate/containment operator over the same. For the expression that was not chosen, the solver will not generate any verification error for the following conditions. x/z values on state variables Null pointer errors Out of bounds array index errors

Consider Example 5-67. Example 5-44


class problem{ rand integer buf[5]; constraint out_of_bounds{ /* When i = 4, buf[i+1] = buf[5] is an out of bounds\array index*/ foreach(buf,i){ buf.sum() with i:(buf[i+1]) == 10; } } } program run_time_error{ problem p = new; void = p.randomize(); }

Randomization in Vera 5-56

The solver will generate the following error for this example.
Constraint solver failed - Constrained entry in rand array is outside of the size. ERROR: Vera Runtime : Fatal Error Location: CALL in program run_time_error (bounds.vr, line 17, cycle 0); READY in function problem.randomize (bounds.vr, line 12, cycle 0)

Consider a minor variation of the same example, where the aggregate expression is guarded using an appropriate ternary operator. Example 5-45
class problem{ rand integer buf[5]; constraint guarded{ /* When i < 4, buf[i+1]are valid array indices */ foreach(buf,i){ buf.sum() with i: ( i<4 ? buf[i+1]:0) == 10; } } } program no_run_time_error{ problem p = new; void = p.randomize(); }

In this case, the solver will not generate a verification error, as buf[i+1] is appropriately guarded.

Default Constraints
Default constraints can be specified by placing the keyword default ahead of a constraint block definition.
[default] constraint constraint_name {constraint_expressions}

Randomization in Vera 5-57

A default constraint for a particular variable is deemed applicable if no other non-default constraints apply to that variable. The solver will satisfy all applicable default constraints for all variables. If the applicable default constraints cannot be satisfied, the solver will generate a solver failure. Example 5-46 illustrates the specification of default constraints. Example 5-46 Default Constraint
default constraint foo{ x > 0; x < 5; }

If no other non-default constraints apply to variable x, then the solver will satisfy the specified default constraints. Properties of Default Constraints. All constraint expressions in a default constraint block are considered to be default constraints. Multiple default constraints, possibly in multiple constraint blocks, can be specified for multiple random variables and are solved together. The status of a default constraint block can be queried using constraint_mode(), and can turned ON or OFF. Unnamed constraint blocks (that is, randomize() with) cannot be defined as default. The compiler will generate an error. A default constraint block can refer to any variable visible in the scope where it is declared.

Randomization in Vera 5-58

A default constraint block can be defined externally (that is, in a different file from the one in which the constraint block is declared). Ordering constraints are allowed in default blocks, but these constraints will be treated as non-default constraints.

Overriding default constraints. The default variables of a default constraint are defined as those variables that are rand and are rand mode ON and part of the default constraint. Default constraints will be applied when they are not overridden by any non-default constraints and contain at least one default variable. Default constraints that do not contain any default variables are ignored. To override a default constraint, a non-default constraint should satisfy the following properties: The constraint mode for the constraint block that contains the non-default constraint is ON, or is inside a randomize-with constraint block. The non-default constraint contains at least one default variable of the default constraint. If the default variable is on the right-hand side of the guarded constraint, the guard has to be true. This holds whether or not the guard has random variables. The non-default constraint should not be an ordering constraint.

If the default variable is in the guard of the non-default constraint, the non-default constraint does not override the default constraint for that variable.

Randomization in Vera 5-59

A default constraint does not override other default constraints under any condition. Thus, if all constraint blocks are declared as default, then none of them will be overridden. Example 5-47
class C { rand reg[3:0] x; default constraint c1 {x == 0;} } class D extends C { constraint d1 {x > 5;} } program P { D d = new(); void = d.randomize(); void = d.constraint_mode(OFF, "d1"); void = d.randomize(); }

In Example 5-47, the default constraint in block c1 is overridden by the non-default constraint in block d1. The first call to randomize picks a value between 6 and 15 for x, since the non-default constraint is applicable. The default constraint is ignored. The second call switches off the non-default constraint, and a value of 0 will be picked for x in the call to randomize. Here, the default constraint is applied. Example 5-48
class C { rand reg[3:0] x; default constraint c1 {x >= 3; x <= 5;} } class D { C c; reg y; constraint d1 {y => c.x > 5;} } program P { D d = new();

Randomization in Vera 5-60

d.c = new(); d.y = 1; void = d.randomize(); d.y = 0; void = d.randomize(); }

In Example 5-48, the default constraint in block c1 is overridden by the non-default constraint in block d1. The first call to randomize will pick a value between 6 and 15 for x, since the non-default constraint is applicable, given that the guard evaluates to TRUE. The default constraint is ignored. The guard for the non-default constraint evaluates to FALSE in the second call, and a value of between 3 and 5 will be picked for x in the next call to randomize. In this randomize() call, the default constraint is applied. Example 5-49
class A { rand reg[3:0] x; rand reg[3:0] y; default constraint T { x == 10 ; y == 10; } constraint E { y == 0; } task post_randomize() { printf("x = %0d y = %0d } } program test { integer ret; A a = new; ret = a.randomize(); }

Randomization in Vera 5-61

Example 5-49 output


x = 10 y = 0 EXPLANATION x = 10 since only the second constraint in the default constraint block is overridden.

Example 5-50
#include "vera_defines.vrh" class A { rand reg[3:0] x; rand reg[3:0] y; rand reg g; default constraint T { x + y == 10 ; } constraint E { g => y == 1; } task post_randomize() { printf("x = %0d y = %0d g = %0d } } program test { integer ret; A a = new; printf("First call to randomize, the guard g evaluates to FALSE\n"); ret = a.randomize() with {a.g == 0;}; printf("Second call to randomize, the guard g evaluates to TRUE\n"); ret = a.randomize() with {a.g == 1;}; printf("Third call to randomize, constraint mode of constraint block E is OFF \n"); ret = a.constraint_mode(OFF, "E"); ret = a.rand_mode(OFF, "g"); ret = a.randomize(); }

Randomization in Vera 5-62

Example 5-50 output:


First call to randomize,the guard g evaluates to FALSE x = 9 y = 1 g = 0 Second call to randomize,the guard g evaluates to TRUE x = 3 y = 1 g = 1 Third call to randomize, constraint mode of constraint block E is OFF x = 1 y = 9 g = 1

In the first call to randomize, the guard is evaluated to FALSE. Therefore, the constraint does not override the default constraint and consequently x + y == 10. In the second call to randomize, the guard is evaluated to TRUE.Therefore, since the non-default constraint is valid and it overrides the default constraint. In the third call to randomize, the constraint block is turned OFF. Since the non-default constraint is turned off, the default constraint is not overridden and x + y == 10. Example 5-51
#include "vera_defines.vrh" class A{ rand reg[3:0] x; rand reg[3:0] y; default constraint T { x + y == 10 ; } task post_randomize() { printf("x = %0d y = %0d } } program test{ integer ret; A a = new; printf("First call to randomize, rand mode of x and y are ON ret = a.randomize(); printf("Second call to randomize, rand mode of x and y are OFF ret = a.rand_mode(OFF , "x"); ret = a.rand_mode(OFF , "y"); a.x = 0; a.y = 0; ret = a.randomize(); printf("Return status of randomize is %0d }

Randomization in Vera 5-63

Output for Example 5-51


First call to randomize, rand mode of x and y are ON x = 3 y = 7 Second call to randomize, rand mode of x and y are OFF x = 0 y = 0 Return status of randomize is 1

In the first call to randomize, the default is not overridden and consequently, x + y == 10; In the second call to randomize, the rand mode of x and y are turned OFF and both are set to 0. The default constraint is ignored since they do not contain any default variables. If the default constraint had not been ignored the return status would have been 0 since randomize would have failed.

Variable Ordering
The Vera solver assures that the random values are selected to give a uniform value distribution over legal value combinations (that is, all combinations of values have the same probability of being chosen). This important property guarantees that all value combinations are equally probable. Sometimes however, it is desirable to force certain combinations to occur more frequently. Consider this case where a 1-bit control variable (s) constrains a 32-bit data value (d): Example 5-52
class B { rand reg s; rand reg[31:0] d; constraint c { s => d == 0;} }

Randomization in Vera 5-64

The constraint c says s implies d equals zero. Although this reads as if s determines d, in fact s and d are determined together. There are 2**32 valid combinations of {s,d}, but s is only true for {1,0}. Thus, the probability that s is 1 will be 1/2**32, which is almost never. Note: This comment reflects a uniform sampling of the entire solution space, and applies to the non-default solver choice. Please see the section on Solver Choice on page 5-107. Vera provides a mechanism for ordering variables so that s can be chosen independent of d. This mechanism defines a partial ordering on the evaluation of variables, and is specified using the solve-before keywords. Example 5-53
class B { rand reg s; rand reg[31:0] d; constraint c { s => d == 0;} constraint order { solve s before d;} }

In this case, the order constraint instructs Vera to solve for s before solving for d. The effect is that s is now chosen true with 50% probability, and then d is chosen subject to the value of s. Accordingly, d == 0 will occur 50% of the time, and d != 0 will occur for the other 50%. Variable ordering can be used to force selected corner cases to occur more frequently than they would otherwise.

Randomization in Vera 5-65

solve-before Syntax for solve-before


solve variable_list before variable_list [hard];

variable_list This is a comma-separated list of: - Integral scalar variables (integer, reg, or enum) - Numeric arrays (bit vector, integer, or enum) of all array types (fixed size, dynamic, and associative) - Smart queues - Object members hard The keyword hard is optional. The use of hard solve-before imposes an ordering between the variables. This section focuses on the semantics of solve-before without the hard keyword. See solve-before hard on page 5-73 for full details. The following restrictions apply to variable ordering: The variables can only be those declared as rand or randc. The variables must be: - Integral scalar variables (integer, reg, or enum) - Numeric arrays (bit vector, integer, or enum) of all array types (fixed size, dynamic, and associative) - Smart queues - Object members
Randomization in Vera 5-66

Example 5-54
rand integer a[$], c[$]; rand integer b; 1. solve a before b; is equivalent to foreach(a,i) solve a[i] before b; 2. solve a, c before b; is equivalent to foreach(a,i) solve a[i] before b; foreach(c,j) solve c[j] before b; 3. solve a before c; is equivalent to foreach(a,i) foreach(c,j) solve a[i] before c[j];

A named constraint block member of a class may contain both regular value constraints and ordering constraints. A randomize-with constraint block in a task or function may contain both value constraints and ordering constraints. Ordering constraints must occur at the top-level of the randomize-with constraint block. Circular dependencies are allowed when specifying variable ordering. In such a case, all the variables that have a circular dependency are solved for together. Variables that are not explicitly ordered will be solved with the last set of ordered variables. These values are deferred until as late as possible to assure a good distribution of value. Variables can be solved for in an order that is not consistent with the ordering constraints. An example situation where this might occur is:

Randomization in Vera 5-67

Example 5-55
x == 0; x < y; solve y before x;

In this case, since x has only one possible assignment (0), x can be solved for before y. The constraint solver uses this flexibility to speed up the solving process. Specification of guards for solve-before constraints inside foreach loops Elaboration guards can be specified for solve-before constructs that occur inside foreach loops. Example 5-56
rand integer x[]; constraint b1{ x.size() in{2,3}; foreach(x,i){ i> 0 => solve x[i-1] before x[i] hard; } }

If a guard expression is specified for any solve-before construct inside a foreach loop, then such a guard expression will be evaluated for every applicable value of the corresponding index variable. The solver will elaborate the relevant solve-before construct only for those values of the corresponding index variable that result in a TRUE value for the guard expression. Example 5-57
rand integer x[]; constraint b1 { x.size() == 3; foreach(x,i) { i > 0 => solve x[i-1] before x[i] hard; }

Randomization in Vera 5-68

For the above example, the solver will expand the specified solve before construct into solve x[0] before x[1] hard and solve x[1] before x[2] hard.

Unidirectional Constraints
The current extension to the constraint language allows the specification of partition points in the constraint set using the unary function void() or using the hard keyword in conjunction with solve-before, improving the performance and capacity of the solver system. void() solve-before hard

void(). The constraint language allows the use of built-in unary identity function, void(). Any valid constraint expression can be a parameter to the void() function. Syntax
function return_type void(expression);

return_type Is the same as that of expression. expression Can be any valid constraint expression. Example 5-58
constraint b1{ y in {2,3}; x % void(y) == 0; }

Randomization in Vera 5-69

Semantics The void() function imposes an ordering among the variables. All parameters to void() function calls in a constraint are solved for before the constraint is solved. The support set of a constraint (that is, the set of variables that participate in that constraint) is split into two sets, namely, those that are void() parameters, and those that are not void() parameters. 1. The constraint is not considered for solving when the function parameters incident on it are solved, that is, the function parameters are solved before the constraint is solved. 2. The constraint can be solved when any of the non-function parameters incident on it are solved. 3. The constraint is solved when at least one non-function parameter incident on it is solved, unless the constraint has no non-function parameters incident on it. In that case, the constraint acts as a checker. 4. When the constraint is solved, all previously unsolved non-function parameters incident on it get solved. 5. The ordering directives derived from the use of void in constraints in OFF constraint blocks are ignored, and do not affect partitioning in any way. Consider the following constraint block in Example 5-59:

Randomization in Vera 5-70

Example 5-59
constraint b1{ y in{2,3}; x % void(y) == 0; x != (y+r); z == void(x*y) r == 5; }

Table 5-2
Constraint
y in {2,3}; x%void(y)==0; x!=(y+r); z==void(x*y); r == 5; x,y y

Function Parameter

Non-Function Parameter
y x x,y.r z r

Figure 5-1

Figure 5-1 represents the dependencies between the variables. y must be solved before x (see x% void(y) ==0;). y and x must be solved before z (see z==void(x*y);). Therefore, the solving order is y, x and then z. When can r be solved for? Can r be solved at the same time as y?

Randomization in Vera 5-71

Consider the constraint x !=(y+r). If no solving order is specified by unidirectional constraints, then r can be solved at the same time as y and x. However, because of the existence of x% void(y) ==0 in the same constraint block, an ordering is imposed. y, which is a function parameter in x%void(y) ==0, must be solved before x. This means that the three variables cannot be solved for at the same time in x!=(y+r). y is solved in y in{2,3}, before x and r are solved. Can r be solved at the same time as x? Consider x !=(y+r) again. Figure 5-1 illustrates that the relationship between r and x is bidirectional (that is, there is no unidirectional constraint imposed between these two variables -there is no ordering dependency between x and r). Therefore, they can be solved at the same time. The solving order: 1. y 2. x and r 3. z The constraints used for solving x,y, z and r: 1. y is solved using the constraint y in {2,3}. 2. x and r are solved using the constraints x%y == 0, x!=y+r and r==5. 3. z is solved using the constraints z==x*y. A warning message will be issued for the following usage of void():

Randomization in Vera 5-72

the entire constraint expression being the parameter to void() (for example, constraint b1 {void(x<y);} - The runtime will ignore the void() specification.

Expressions purely over constants and state variables, including loop variables in the case of array constraints, being parameters to void() (for example, constraint b1{x==void(5);} - the runtime will ignore the void() specification.

A void() function being applied to a sub-expression of the parameter of another void() function (for example, constraint b1{x==void(y + void(z));} - the runtime will ignore the nested void() specifications (that is, same as x==void(y+z).

In cases where the compiler cannot detect such conditions, no warning will be issued by the runtime. solve-before hard. The solve-before construct allows for an optional hard modifier. Example 5-60
constraint b1{ y in(2,3}; x%y == 0; solve y before x hard; }

The use of hard solve-before imposes an ordering between the variables. The ordering can be used to assign a priority order to each variable. A higher priority indicates that the variable should be solved earlier.

Randomization in Vera 5-73

Array Variable: If the argument to solve before hard is an array. Similar to solve-before, an array is expanded into its individual elements before ordering is imposed. See page 5-66 for examples on how this happens. The set of variables incident on a constraint is split into two sets those at the lowest priority among the incident variables and those not at the lowest priority. Then the following semantic rules apply: 1. The constraint is not considered when any but the lowest priority variables incident on it are solved (that is, the higher priority variables are solved before the constraint is solved. 2. The constraint is solved when the lowest priority variables incident on it are solved. 3. When the constraint is solved, all lowest priority variables incident on it get solved. 4. hard solve-before constraints in OFF constraint blocks are ignored, and do not affect partitioning in any way. Example 5-61
constraint b1 { y in {2,3}; x % y == 0; x != y; z == x * y; solve y before x hard; solve x before z hard; }

Randomization in Vera 5-74

Table 5-3
Constraint
y in{2,3}; x%y == 0; x !=y; z==x*y; y y x,y

Early

Late
y x x z

Figure 5-2 Dependencies between variables

The constraint(s) used for solving x,y and z: 1. y is solved using the constraint: y in(2,3}; 2. x is solved using the constraints: x%y == 0; x!=y; 3. z is solved using the constraint: z ==x*y; The sequence in which the constraints will be solved is exactly as listed in the previous section. solve-hard before and void(). void() and solve-before hard have the same behavior regarding partitioning the solver-space (that is, every randomized variable inside the void() or solve-before hard is solved first and set to static values prior to randomizing any other variables in the constraint). The difference is that you can use the void construct as part of the expression, whereas solve-before hard is on a separate line, by itself).

Randomization in Vera 5-75

Effect of rand_mode on Unidirectional Constraints. Using rand_mode to turn a variable OFF has the same effect as declaring the variable as non-random. Thus, ordering directives on it are dropped. This has the side effect of dropping some transitive ordering relationships as well. For example in:. Example 5-62
constraint b1 { y in {2,3}; x % void(y) == 0; x != y; z == void(x); }

If x were to be turned OFF, then there would be no ordering relationship left between y and z either. Extensions to Semantics. The introduction of unidirectional constructs has resulted in extensions to the semantics of numerous pre-existing constraint constructs. Semantics of solve-before construct without the hard modifier The solve-before constraints that are not modified by the hard directive will be used together in a partition. Thus, the non-hard solve-before constraints will not affect the partitioning, but will affect the order of variable assignment within a partition, very much like they affect the order of variable assigning on the complete problem prior to this release. This is illustrated by the following example:

Randomization in Vera 5-76

Example 5-63
constraint b1 { y in {2,3}; x % y == 0; x != y; z == void(x * z); solve y, z before x; }

The sequence in which the constraints are solved is: 1. x, y are solved using the constraints y in{2,3}; x%y == 0; solve y before x;. 2. z is solved using the constraint z == x*y; Note that since x is already solved at this point, the constraint solve z before x is irrelevant and hence dropped. Semantics for Array Constraints (Solving Array Sizes) Either of the two constructs defined above can be used to determine the partition to be solved when solving for the size of an array. The following example is used to illustrate the semantics: Example 5-64
class B { rand integer x[$]; rand bit[1:0] k; constraint b1 { x.size() == k; k != 2; foreach(x, i) { void(k-1) == i => x[i] == 0; } } }

The constraints x.size() = k; k != 2; are solved for, since the use of the void() function call renders k unconstrained in the constraint inside the foreach loop.

Randomization in Vera 5-77

The use of void() in this example specifies that k is solved for before any of the members of the x array. The following example illustrates the other important semantic: Example 5-65
class B { rand integer x[$]; rand bit[1:0] k; constraint b1 { x.size() == void(k); k != 2; foreach(x, i) { k-1 == i => x[i] == 0; } } }

In this case, k has to be solved before x.size(), and x.size() needs to be solved before the foreach loop is expanded. Hence, there is an implicit ordering between x.size() and x[i], requiring that x.size() gets solved first. As a result, the sequence in which the constraints will be solved: 1. k is solved for using the constraints k !=2. 2. x.size() is solved for using the constraints x.size() == k:. 3. The loop is expanded and all the members of the x array are solved for. The semantics of array constraints in the presence of void calls are as follows: 1. Implicit ordering relations are introduced between array sizes and members of the array, *only* those with variable expressions in the index.

Randomization in Vera 5-78

Array sizes are solved before the constraints inside loops are solved or constraints involving array aggregate methods calls are solved.

Semantics of Default Constraints With the introduction of partitions, it is possible that some random variables over which constraints are defined are solved before the default constraint itself. In such a case, the solver will consider previously solved random variables like state variables. When the default constraint is solved, it is disabled only if any of the currently being solved random variables incident on it are overridden. This is consistent with current semantics of default constraints, when considered in the context of the partition being solved. Consider this example: Example 5-66
default constraint b1 { x <= y; } constraint b1 { z == void(y); z => x == 0; y in {0, 1}; }

The sequence in which the constraints will be solved is: 1. y is solved using the constraint y in{0,1}. 2. z, x are solved using the default constraint x<=y and the non-default constraints z==y; z=>x ==0;. the default constraint applies if and only if z is 0 (that is, if and only if y was chosen as 0 in the previous partition.).

Randomization in Vera 5-79

Semantics of randc There is an existing semantic of the solver, wherein randc variables are solved in partitions that contain a single randc variable, after which they behave like state variables when solving for non-randc rand variables. Example 5-67
randc bit[3:0]x; rand bit[3:0] y,z; constraint b1{ y in{0,1}; x<12; if(y){ x<5; } else{ x<10; } z>x; }

The sequence in which the above constraints are solved is: 1. x is solved for using the constraint x<12. 2. y and z are solved for using the remaining constraints. Note that this could result in a failure, depending on the solution picked in the previous step. For example, if x were picked as 11 in the previous step, then there would be no solution for y in this step. Thus, all randc variables are solved before all rand variables. However, when unidirectional constraints are used in the presence of randc variables, it is possible that rand variables could be solved before randc variables.

Randomization in Vera 5-80

Example 5-68
randc bit[3:0]x; rand bit[3:0] y,z; constraint b1{ y in{0,1}; x<12; if(void(y)){ x<5; } else{ x<10; } z>x; }

The sequence in which the constraints are solved is: 1. y is solved using the constraint y in{0,1}. 2. x is solved using the constraints if(y) x<5 else x<10; x<12. 3. z is solved using the constraint z>x.

Function Calls in Constraints


User-defined functions can be called from inside constraints declarations. They are used to define complex expressions that can be solved in procedural code and which do not need to be solved declaratively. However, these functions need to comply with certain coding guidelines. Compartmentalizing code in functions improves readability and enhances reuse of constraints. Further, the efficiency of constraint solver is improved. The solving order imposed by calling user-defined functions in constraints follows the same semantics as that of the void() function.

Randomization in Vera 5-81

Pure Functions. Calling a general function from inside constraints can have undesired side effects. When a call to randomize is made, the solver collects all the state information (values of non rand variables, constraint mode of constraint blocks, rand mode of rand variables etc.) before solving for the variables. If this state information is changed in the function, the results of the solver might be inconsistent. Also owing to the presence of unidirectional constraints, the results of the rand variables are computed in stages. If the function called from inside constraints changes the value of variables already solved for in an earlier stage, it will result in inconsistencies. Both these inconsistencies are illustrated in the example below. Example 5-69
function integer pfun(void){ global_var = 2; a.b = 2; pfun = a.b; } class A { rand integer a,b,c; constraint C {a == global_var; constraint D { solve b before c hard; b==3; c==pfun(); } } program test { integer global_var = 3; A a = new; void = a.randomize(); }

In Example 5-69, a will be evaluated to the value of global_var (3), b will be evaluated to 3, and then foo will be called.
Randomization in Vera 5-82

In pfun, global_var is changed to value 2 and a.b is changed to value 2 and the function returns the value 2. Then c is evaluated to 2. This results in the inconsistency that even though a == global_var, the values of global_var is different from a. Also c has a different value from b, even though it is implied that c == a.b. To prevent these kinds of inconsistencies by accident, function calls called from inside constraints have to be declared as pure. Pure functions can be called from inside constraints as well as outside constraints. Pure functions have a set of requirements that need to be met so that the above inconsistencies can be prevented. Requirements of Pure Function. The following guidelines must be followed when developing functions to be called from constraint blocks. The function must be global and declared with the keyword, pure. Calling a pure class method from a constraint is not supported.
pure function integer myfunc(integer a){ myfunc = a*2; }

Pure function arguments can only be numeric or numeric array types (bit vectors, integer and enum). Arguments are passed by value only. Passing by reference (that is, a var argument) is not supported. The following are examples of illegal arguments:
//string argument pure function integer myfunc(string s){}

Randomization in Vera 5-83

//virtual port argument pure function integer myfunc(portA a){} //class argument pure function integer myfunc(classB b){} //var argument pure function integer myfunc(var integer i){}

Pure functions can only access local variables and arguments passed to the function. They cannot access members of global objects. Global variables can be passed to a function call but cannot be directly accessed inside a pure function.

Example 5-70
class A{ ... constraint con{ rand_var == myfunc(global_var); //allowed } ... } pure function integer myfunc(integer num){ integer local_var; A local_obj = new(); // where A is a class // illegal assignments that will result in a compilation // error // local_var = global_var; // local_var = global_obj.i;// where i is a class member // global_obj.i = local_var;// where i is a class member // local_obj = global_obj; // global_obj = local_obj; // allowed local_var = num; local_obj.i = num;// where i is a class member . } program test{ integer global_var; A global_obj = new();// where A is a class . }

Randomization in Vera 5-84

Pure functions cannot contain blocking statements. The following constructs are not allowed. - fork and join - drive, expect and blocking samples

Pure functions can contain only the following system or method calls: - Random number generator system calls (for example, random(), urandom(), etc.) - Pack and unpack system call, for example, vera_pack(), vera_pack_big_endian(), etc. - vera_crc() - String methods (for example, len(), match(), atoi(), etc.) - I/O methods (for example, printf(), fprintf(), etc.) Calling the randomize() function or other system or method calls is not allowed.

The randseq and randcase constructs are allowed.

Semantics of Parameter Ordering. The solving order imposed by calling user-defined functions in constraints follows the same semantics as that of the void() function. Random variables of a constraint are grouped into two categories: function parameters and non-function parameters. All function parameters are solved before the constraint is solved. See page 5-70 for the semantic rules.

Randomization in Vera 5-85

Example 5-71
class A{ rand bit[3:0] y; rand integer x; constraint con{ y > 5; x == myfunc(y); } } pure function integer myfunc(bit[15:0] num){ myfunc = num * 10; }

The solving order is: y is solved using constraint y > 5 myfunc() is called x is solved using constraint x == myfunc() and the returned value of myfunc().

Array Parameters. For pure functions with numeric array parameters, each array member is treated as a separate parameter. Semantic rules of solving order apply to each array member. See page 5-74 for the semantic rules. In addition, if the array size is random, the size is solved before the constraint with the function call is solved. Example 5-72
class A { rand integer p[$]; rand integer m; constraint C { p.size() == 5; m == min(p); foreach(p,i){p[i] == i;} } }

Randomization in Vera 5-86

The solving order is: The array size is solved using constraint p.size() == 5; The array members, p[0] to p[p.size()-1], are solved using the foreach constraint p[i] == i; The function min() is called The integer m is solved using constraint m == min(p) and the returned value of min()

Function Calls in Solver Trace. The solver trace has been enhanced to print the following function call information before each solver problem or partition is printed. Function name Function arguments Parameters passed to function call Return value of function call

Static Constraint Blocks and Random Variables


A constraint block can be defined as static by including the static keyword in the definition. The syntax is:
static constraint

constraint_name{constraint_expression}

If a constraint block is declared as static, then calls to constraint_mode() (see page 5-101) affect all instances of the specified constraint in all objects. So if a static constraint is set to OFF, it is OFF for all instances.
Randomization in Vera 5-87

Randomize Methods
Variables in an object are randomized using the randomize() class method. Every class has a built-in randomize() virtual method. Syntax
virtual function integer randomize([integer options=0]);

options The options parameter involves one or more of the following: Table 5-4
Macro argument
VERA_SOLVE_MODE VERA_CHECK_MODE VERA_ENABLE_SOLVER_DIAGNOSTICS_0 VERA_ENABLE_SOLVER_DIAGNOSTICS_1 VERA_ENABLE_SOLVER_DIAGNOSTICS_2 VERA_ENABLE_SOLVER_DIAGNOSTICS_3 VERA_ENABLE_SOLVER_DIAGNOSTICS_4 VERA_ENABLE_SOLVER_DIAGNOSTICS_ON_FAILURE_0 VERA_ENABLE_SOLVER_DIAGNOSTICS_ON_FAILURE_1 VERA_ENABLE_SOLVER_DIAGNOSTICS_ON_FAILURE_2 VERA_ENABLE_SOLVER_TRACE_0 VERA_ENABLE_SOLVER_TRACE_1 VERA_ENABLE_SOLVER_TRACE_2 VERA_ENABLE_SOLVER_TRACE_ON_FAILURE_0 VERA_ENABLE_SOLVER_TRACE_ON_FAILURE_1 VERA_ENABLE_SOLVER_TRACE_ON_FAILURE_2 VERA_ENABLE_SOLVER_TRACE_ON_FAILURE_3 VERA_ENABLE_CHECKER_TRACE_0 VERA_ENABLE_CHECKER_TRACE_1 VERA_ENABLE_CHECKER_TRACE_2

Equivalent runtime option and setting


Not Applicable Not Applicable +vera_enable_solver_diagnostics=0 +vera_enable_solver_diagnostics=1 +vera_enable_solver_diagnostics=2 +vera_enable_solver_diagnostics=3 +vera_enable_solver_diagnostics=4 +vera_enable_solver_diagnostics_on_failure=0 +vera_enable_solver_diagnostics_on_failure=1 +vera_enable_solver_diagnostics_on_failure=2 +vera_enable_solver_trace=0 +vera_enable_solver_trace=1 +vera_enable_solver_trace=2 +vera_enable_solver_trace_on_failure=0 +vera_enable_solver_trace_on_failure | vera_enable_checker_trace_on_failure=1 +vera_enable_solver_trace_on_failure=2 +vera_enable_solver_trace_on_failure=3 +vera_enable_checker_trace=0 +vera_enable_checker_trace=1 +vera_enable_checker_trace=2

Randomization in Vera 5-88

Table 5-4
Macro argument
VERA_ENABLE_CHECKER_TRACE_FAILURE_0 VERA_ENABLE_CHECKER_TRACE_FAILURE_1 VERA_ENABLE_CHECKER_TRACE_FAILURE_2 VERA_ENABLE_CHECKER_TRACE_FAILURE_3 VERA_SOLVER_MODE_1 VERA_SOLVER_MODE_1

Equivalent runtime option and setting


+vera_enable_checker_trace_on_failure=0 +vera_enable_checker_trace_on_failure=1 +vera_enable_checker_trace_on_failure=2 +vera_enable_checker_trace_on_failure=3 +vera_solver_mode=1 +vera_solver_mode=2

The above macros are defined in <vera_defines.vrh> Note: For discussion of VERA_CHECK_MODE and VERA_SOLVE_MODE, see page 5-92. Options that are not compatible with each other will result in compile-time or runtime errors. For example, When an option specifies using both the VERA_CHECK_MODE and also specifies a VERA_ENABLE_SOLVER_TRACE or VERA_ENABLE_SOLVER_TRACE_ON_FAILURE mode, this will result in an error since both cannot be used in the same call. When an option specifies both VERA_SOLVE_MODE and VERA_ENABLE_CHECKER_TRACE or VERA_ENABLE_CHECKER_TRACE_ON_FAILURE modes, an error will result When multiple VERA_ENABLE_SOLVER_TRACE or VERA_ENABLE_SOLVER_TRACE_ON_FAILURE modes or multiple VERA_ENABLE_CHECKER_TRACE or VERA_ENABLE_CHECKER_TRACE_ON_FAILURE are specified in a per-call option, an error will be issued

Randomization in Vera 5-89

Options that are not specified in the per-call options will either take the values in the command line if specified or if not specified in the command line, they will take their default values. Error checking will not consider command-line arguments. The order in which these options are checked is: per-call option command line plus argument proj file .ini file shell environment variable

For example, options specified by the per-call option will override options specified on the command line. If an option is not specified in the per-call option and is specified in the command line, the command line option will be taken. Examples:
ret = a.randomize(VERA_SOLVER_MODE_1 | VERA_ENABLE_SOLVER_TRACE_2);

If the above were the only call to randomize() in the testbench, then it would be equivalent to running the simulation with the options:
+vera_solver_mode=1 +vera_enable_solver_trace=2

Since neither the VERA_SOLVE_MODE nor the VERA_CHECK_MODE mode have been specified, the default value of VERA_SOLVE_MODE will be taken. Next, consider:
ret = a.randomize(VERA_ENABLE_SOLVER_TRACE_1);

Randomization in Vera 5-90

Where, in the command line or .ini file, the options are


+vera_enable_solver_trace=2 +vera_solver_mode=1

This will result in VERA_ENABLE_SOLVER_TRACE_1 overriding the command line argument of +vera_enable_solver_trace=2. The +vera_solver_mode=1 is not impacted. Examples that result in a compile-time error:
ret = a.randomize(VERA_ENABLE_SOLVER_TRACE_1 | VERA_ENABLE_SOLVER_TRACE_2);

or
ret = a.randomize(VERA_ENABLE_SOLVER_TRACE_1 | VERA_CHECK_MODE);

Example that results in a runtime error:


val = VERA_ENABLE_SOLVER_TRACE_1 | VERA_ENABLE_SOLVER_TRACE_2; ret = a.randomize(val);

Here is another, more extensive example:


ret_val = obj.randomize(VERA_SOLVE_MODE | VERA_ENABLE_SOLVER_TRACE_0 | VERA_ENABLE_SOLVER_TRACE_ON_FAILURE_0);

Note that these options will have the following effects: 1. Inconsistent constraints will result in a return value of 0, and no messages to the log file. (This is a non-backwards compatible modification to the current behavior for +vera_enable_solver_trace_on_failure=0, which issues a single line error message to the log file) 2. Fatal errors (null pointers, array out of bounds, and x/z values on state variables) and solver time-outs will result in messages to the log file. This is the same as the default behavior, (that is, one without special options).

Randomization in Vera 5-91

3. If error_mode(ON, EC_RANDOMIZEFAILURE) was called before the call to randomize() then inconsistent constraints and solver time-outs will result in a verification failure. If this is not desired, then the user needs to call error_mode(OFF, EC_RANDOMIZEFAILURE) before the call to randomize(). This is the same as the default behavior, (that is, one without special options). VERA_SOLVE_MODE and VERA_CHECK_MODE In the VERA_SOLVE_MODE mode, values satisfying all active constraints are selected and assigned to rand and randc variables. randomize() is a virtual method which, in the VERA_SOLVE_MODE mode, generates random values for all the active random variables in the object, subject to the active constraints. The randomize() method returns OK if it successfully sets all the random variables and objects to valid values, otherwise it returns FAIL. In the VERA_CHECK_MODE mode, if all active constraints are satisfied given the current values of all variables (rand, randc and non-rand), a call to randomize(VERA_CHECK_MODE) returns OK. If the constraints fail, the call returns FAIL. The values of random variables do not change as a result of a call to randomize(VERA_CHECK_MODE). In all calls to randomize(VERA_CHECK_MODE), random variables are treated as if rand_mode() were set to OFF. However, all calls to randomize([VERA_SOLVE_MODE]) are subject to the actual rand_mode() specification. If VERA_SOLVE_MODE or VERA_CHECK_MODE is not specified, the default behavior is that of VERA_SOLVE_MODE.

Randomization in Vera 5-92

Example 5-73
class SimpleSum{ rand reg[7:0] x, y, z; constraint c {z == x + y;} }

This class definition in Example 5-73 declares three random variables, x, y, and z. To randomize an instance of class SimpleSum, call the randomize() method: Example 5-74 randomize(VERA_SOLVE_MODE)
SimpleSum p = new; integer success = p.randomize(VERA_SOLVE_MODE); if (success == OK ) ...

Assuming the class definition in Example 5-73, Example 5-75 is a case of calling randomize(VERA_CHECK_MODE). Example 5-75
SimpleSum p = new; integer success; p.z = 5; p.x = 3; p.y = 2; success = p.randomize(VERA_CHECK_MODE); if (success == OK ) ...

Best practice: Verifying the status of the randomize() call is always recommended even if you know that the constraints can always be satisfied. This is recommended because the actual value of state variables or addition of constraints in derived classes may render seemingly simple constraints unsatisfiable.

Randomization in Vera 5-93

Inline Constraints Using "randomize() with"


By using the randomize() with construct, you can declare inline constraints at the point where the randomize() method is called. These additional constraints are applied along with the object constraints. Syntax
result = class_object_name.randomize([integer mode]) with constraint_block;

class_object_name Is the name of the instantiated object. mode Can be either VERA_CHECK_MODE or VERA_SOLVE_MODE. If mode is not specified, the default behavior is that of VERA_SOLVE_MODE. constraint_block Is an anonymous constraint block. The constraint_block contains the additional inline constraints to be applied along with the object constraints declared in the class. Example 5-76
class SimpleSum{ rand reg[7:0] x, y, z; constraint c {z == x + y;} } task InlineConstraintDemo(SimpleSum p){ integer success; success = p.randomize() with {x < y;}; }

This is the same example used above, however, randomize() with is used to introduce an additional constraint that x < y.

Randomization in Vera 5-94

The randomize() with construct can be used anywhere a Vera expression can appear. The constraint block following with can define all of the same constraint types and forms as would otherwise be declared in a class. The randomize() with constraint block may also reference local variables and task and function parameters, eliminating the need for mirroring a local state as member variables in the object class. The scope for variable names in a constraint block, from inner to outer, is: randomize() with object class, automatic and local variables, task and function parameters, class variables, global variables. The randomize() with class is brought into scope at the innermost nesting level. For instance, see the scoping example below, where the randomize() with class is Foo. Example 5-77
class Foo{ rand integer x; } class Bar{ integer x; integer y; task doit(Foo foo, integer x, integer z ){ integer result; result = foo.randomize() with {x < y + z; }; } }

In the foo.randomize() with constraint block, x is a member of Foo (randomize-with) and hides Bar::x. It also hides the doit() task parameter x. y is a member of Bar. z is a local parameter.

Randomization in Vera 5-95

If you overload these methods you must call their associated superclass methods, otherwise their pre- and post-randomization processing steps are skipped.

pre_randomize() and post_randomize()


Every class contains built-in pre_randomize() and post_randomize() tasks, that are automatically called by randomize() before and after it computes new random values.

Built-in definition for pre_randomize():


task pre_randomize([integer options]){ if (super) super.pre_randomize([options]); /* Optional programming before randomization goes here. */ }

Built-in definition for post_randomize():


task post_randomize([integer options]){ if (super) super.post_randomize([options]); /* Optional programming after randomization goes here. */ }

When obj.randomize() is invoked, it first invokes pre_randomize() on obj and also all of its random object members that are enabled. Pre_randomize() then recursively calls super.pre_randomize(). After the constraints have been solved (options = VERA_SOLVE_MODE) or checked (options = VERA_CHECK_MODE), randomize() invokes post_randomize() on obj and also all of its random object members that are enabled. Post_randomize() then recursively calls super.post_randomize().

Randomization in Vera 5-96

You may overload the pre_randomize() in any class to perform initialization and set pre-conditions before the object is randomized. You may overload the post_randomize() in any class to perform cleanup, print diagnostics, and check post-conditions after the object is randomized. If you overload these methods you must call their associated superclass methods, otherwise their pre- and post-randomization processing steps will be skipped. The pre_randomize() and post_randomize() tasks also have an optional integer argument that takes on the same value as the argument passed by randomize(). The user can control the actions performed by pre_randomize() and post_randomize(), depending on the mode. Example 5-78
#include <vera_defines.vrh>
class C { rand bit x; bit y; constraint R {y => x == 1;} task pre_randomize(integer options) { if (options & VERA_CHECK_MODE) return; y = 1; } } program P { C c = new(); integer ret; void = c.randomize(VERA_SOLVE_MODE); // equivalent to // c.randomize(); void = c.randomize(VERA_CHECK_MODE); }

Randomization in Vera 5-97

NOTES: Random variables declared as static are shared by all instances of the class in which they are declared. Each time the randomize() method is called, the variable is changed in every class instance. If randomize() fails, the constraints are infeasible and the random variables retain their previous values. In this event, the post_randomize() method is not called. The randomize() method is implemented using object random stability. To seed an object, use the srandom() system call, specifying the object in the second argument. The randomize() method may not be overloaded. The built-in pre_randomize() and post_randomize() tasks should not perform blocking operations because their automatic traversal temporarily locks objects from access. If these routines block and another call to randomize attempts to visit the locked object, undefined behavior will occur.

Disabling Random Variables


OpenVera provides the predefined rand_mode() method to control whether a random variable is active or inactive. When a random variable is inactive, it is treated the same as if it had not been declared rand or randc. All random variables are initially active. rand_mode() Syntax
function integer object_name.rand_mode( ON | OFF | REPORT [, string variable_name [,integer index] ]);

Randomization in Vera 5-98

object_name Is the name of the object in which the random variables are defined. Predefined Macros: ON, OFF, and REPORT specify the action
Macro
ON

Action
Sets the specified variables to active so that they are randomized on subsequent calls to the randomize() method. Sets the specified variables to inactive so that they are not randomized on subsequent calls to the randomize() method. Returns the current ON/OFF value for the specified variable.

OFF

REPORT

variable_name Is a string with the name of the variable to be made active or inactive. The variable_name can be the name of any variable in the class hierarchy. If no variable_name is specified, the action is applied to all variables within the specified object. index Is an optional array index. If the variable is an array, omitting the index results in all the elements of the array being affected by the call. An index value of -1 is treated the same as index omission. The rand_mode() method returns the new mode value (either OFF, which is 0, or ON, which is 1) if the change is successful. If the specified variable does not exist within the class hierarchy, the method returns a -1. If the specified variable exists but is not declared as rand or randc, the function returns a -1. If the variable is an array, the array name and index must be specified for a REPORT.

Randomization in Vera 5-99

If the variable is an object, only the mode of the variable is changed. If the variable is an array, then the mode of each array element is changed. Example 5-79
class Packet { rand integer source_value, dest_value; ... other declarations } Packet packet_a = new; integer ret; // Turn all variables off. ret = packet_a.rand_mode (OFF); // ... other code // Enable source_value. ret = packet_a.rand_mode (ON, "source_value");

This example first disables all the random variables in packet, and then enables the source_value variable. The rand_mode() specification can only apply to random variables not defined as local or protected. If this method is used to change a local or protected variable to be active or inactive, a fatal runtime error message is issued. If none of the optional arguments are specified when calling rand_mode(), then all random variables are turned on (off) globally. If an object contains a local or protected random variable, a one-time warning message is issued:
runtime: caller context does not have access permission to all variables. Warning will not be issued again.

In the above scenario, the rand_mode() specification will not apply to the local or protected random variables. In this case, the simulation continues.

Randomization in Vera 5-100

Disabling Constraints
OpenVera provides the predefined constraint_mode() method to control whether a constraint is active or inactive. All constraints are initially active. Syntax
function integer object_name.constraint_mode( ON | OFF | REPORT [, string constraint_name]);

object_name Is the name of the object in which the constraint block is defined. Predefined Macros: ON, OFF, and REPORT specify the action.
Macro
ON

Action
Sets the specified constraint block to active so that it is enforced on subsequent calls to the randomize() method. Sets the specified constraint block to inactive so that it is not enforced on subsequent calls to the randomize() method. Returns the current ON/OFF value for the specified variable.

OFF

REPORT

constraint_name Is the name of the constraint block to be made active or inactive. The constraint name can be the name of any constraint block in the class hierarchy. If no constraint name is specified, the switch is applied to all constraints within the specified object.

Randomization in Vera 5-101

The constraint_mode() method returns the value of switch (either OFF or ON) if the change is successful. If the specified constraint block does not exist within the class hierarchy, the method returns a -1. The constraint name must be specified for a REPORT. Example 5-80
class Packet{ rand integer source_value; constraint filter1{ source_value > 2 * m; } } Packet packet_a = new; integer ret = packet_a.constraint_mode (OFF, "filter1"); // ... other code ret = packet_a.constraint_mode (ON, "filter1");

This example first makes constraint filter1 inactive (OFF) and returns OFF to the variable ret. Then it makes constraint filter1 active (ON) and returns ON to the variable ret. The constraint_mode() specification can only apply to random variables not defined as local or protected. If this methods is used to change a constraint to be active or inactive, a fatal runtime error message is issued. If none of the optional arguments are specified when calling constraint_mode(), then all constraint blocks are turned on (off) globally. If an object contains a local or protected constraint, a one-time warning message is issued:
runtime: constraint_mode caller does not have access permission to all constraint blocks. Warning will not be issued again.

In the above scenario, the constraint_mode() specification will not apply to the local or protected random variables. In this case, the simulation continues.
Randomization in Vera 5-102

The class Packet is defined in Example 5-80. Example 5-81


class DerivedPacket extends Packet { local constraint filter1 { source_value < 2 * m; } } program test { DerivedPacket d = new; Packet packet_a = d; integer ret = packet_a.constraint_mode(OFF , "filter1"); }

The constraint_mode() method behaves in a virtual fashion. Both the base class Packet (defined in Example 5-80) and the derived class DerivedPacket (defined in Example 5-81) have a constraint named filter1. When the constraint mode of filter1 is switched off using the handle, packet_a, which points to an instance of DerivedPacket, the constraint_mode() returns an error since it does not have access permission to filter1 in DerivedPacket (that is, filter1 in the derived class is local).

Dynamic Constraint Modification


There are several ways to dynamically modify constraints on randomization: Implication and if-else style constraints allow you to declare predicated constraints. A constraint block can be made active or inactive by using the constraint_mode() function. Initially, all constraint blocks are active. Inactive constraints are ignored by the randomize() function

Randomization in Vera 5-103

Random variables can be made active or inactive using the rand_mode() function. Initially, all rand and randc variables are active. Inactive variables are ignored by the randomize() function. The weights in a dist constraint can be changed, affecting the probability that particular values in the set are chosen.

Out of Body Declaration of Constraints


Out of body constraints are handled differently, in that they are handled at load time and not compile time. Thus, the class declaration need not be aware of the constraint implementation. The ability to add conditions to existing declared constraints at runtime means: The user does not have to change the original constraint declarations within the class definition.

Debugging Constraints
Vera supports a debug or checker mode that displays diagnostics when Vera executes a randomize(VERA_SOLVE_MODE) call. To enable these modes, use the runtime options vera_enable_solver_trace and vera_enable_checker_trace, repectively. vera_enable_solver_trace | vera_enable_checker_trace Syntax
+vera_enable_solver_trace=[value] +vera_enable_checker_trace=[value]

Randomization in Vera 5-104

The optional value argument can be 0, 1, or 2.


Value
0 1 2

Description
disables tracing enables tracing enables more verbose message in trace

If vera_enable_solver_trace or vera_enable_checker_trace are specified without an argument, the default value is 1. If vera_enable_solver_trace is not specified, the default is 2. If vera_enable_checker_trace is not specified, the default is 0. The option can, alternatively, be put in the .ini file as:
vera_enable_solver_trace=[value] vera_enable_checker_trace=[value]

vera_enable_solver_trace_on_failure | vera_enable_checker_trace_on_failure There are also the vera_enable_solver_trace_on_failure and vera_enable_checker_trace_on_failure runtime options, which are similar to the vera_enable_solver_trace vera_enable_checker_trace options. There are three differences between these options. First, the enable solver trace on failure mode prints trace information only when the solver fails to compute a solution, usually due to inconsistent constraints. Second, when the value of the option is 2, the analysis narrows down to the smallest set of inconsistent constraints, thus aiding the debugging process.

Randomization in Vera 5-105

For example, if the constraints are:


x x y x y == 0; > y; < z+w; == 5; != 6;

Then, if +vera_enable_solver_trace_on_failure=2 is the option with the value of 2, then you will get a report of just the inconsistent constraints. For example:
x == 0; x == 5;

Third, when the value of the option is 3, in addition to the trace information reported using option 2 the solver will print all the constraints that have been solved earlier due to the presents of unidirectional constraints in them. Which, could have lead to the current failing constraint. Syntax
+vera_enable_solver_trace_on_failure =[value]

The optional value argument can be 0, 1, 2 or 3.


Value
0 1 2 3

Description
disables tracing enables tracing enables more verbose message in trace In addition to the message in trace with option 2 the solver reports all the earlier solved constraints. which could have lead to the current failing constraint.

If vera_enable_solver_trace_on_failure or vera_enable_solver_trace_on_failure is specified without an argument, the default value is 1. The default is 2, if

Randomization in Vera 5-106

vera_enable_solver_trace_on_failure is not specified. If the vera_enable_checker_trace_on_failure is not specified, the default is The option can, alternatively, be put in the .ini file as:
vera_enable_solver_trace_on_failure=[value]

vera_enable_checker_trace Default is 0 vera_enable_checker_trace_on_failure Default is 2

Solver Choice
Vera incorporates two different solvers, each of which supports the entire Vera constraint language. You may select the solver you want using the runtime option vera_solver_mode, which takes the values 1 or 2. The default value is 2. Example 5-82
simv +vera_solver_mode=2 ...

The two solvers have different performance characteristics. When the solver mode is set to 1, this solver exhaustively analyzes the entire solution space, restricted to the space allowed by the current assignment to non-random variables. This analysis is cached, and reused in subsequent calls to randomize() with the same combination of non-random variables. Since the solver has a complete view of the solution space, it can generate a uniform sampling of the solutions.

Randomization in Vera 5-107

When the solver mode is set to 2, this solver does an analysis of the solution space too, again restricted to the space allowed by the current assignment to non-random variables. However, it is not exhaustive as with solver mode 1. Consequently, the analysis is faster when the solver mode is set to 2. This solver then follows a heuristic search algorithm when it generates a random solution. Since this solver does not have a complete view of the solution space, it cannot generate a uniform sampling of the solutions. Depending on the nature of constraints, and the number of calls to randomize() made per class, one or the other solver might be more suitable.

Automatic Solver Orchestration


As discussed before, Vera has two general purpose solvers. The user can indicate a preferred solver choice by setting the +vera_solver_mode option at runtime. In addition, there is a specialized solver that applies to simple constraint sets. The system is very adaptive in the selection of the solver, and use the +vera_solver_mode setting is only interpreted as an initial guideline. The behavior of the system is: 1. +vera_solver_mode remains the only user control provided. This setting will specify the preferred solver as either 1 or 2, which are the modes for the two general-purpose solvers mentioned above.

Randomization in Vera 5-108

2. If an analysis of the constraints reveals that the specified constraints are better solved by the non-preferred solver, or by the specialized solver for simple constraints mentioned above, then the preferred solver setting is overridden. Thus, the initial solver choice is determined. 3. If the current solver choice results in a timeout while solving the constraints (timeout limits cannot be controlled by the user), then the solver mode is switched. A timeout cannot occur with the specialized solver, so the switched solver mode is either 1 or 2. 4. If the switched solver choice results in a timeout as well, then a timeout is reported to the user. 5. If the switched solver succeeds, then it remains the current solver choice. 6. Steps 3, 4, 5 are repeated for each call to randomize.

Internal Caching
Vera maintains an internal disk cache for randomization. This cache improves performance and reduces memory use by re-using randomization problem data from previous runs. By default, Vera creates a cache called .__solver_cache__ in the current working directory. You may specify an alternate cache location by specifying the directory location via the runtime option vera_cache_dir. For example: Example 5-83
simv +vera_cache_dir=/u/myself/tmp_cache ...

The contents of the Vera cache can be removed at any time, except when Vera is running. There is no internal caching when +vera_solver_mode=2 is the mode in which the run is done.

Randomization in Vera 5-109

Efficient Use of Constraints


It is important to keep the number of random bits small for any given randomization problem because memory use and CPU time grow quickly for large problems. To this end it is a best practice to: Declare exact-size bit vectors instead of integers, which are internally represented as 32-bit signed values. Use enumerated types instead of a list of integers/bit-vectors for cases where you want to represent constant values (that is, values that will not be changed in the course of the simulation). This allows the compiler to infer the sizes of identifiers automatically. This also allows for writing more maintainable code.

Example 5-84
rand integer x; integer pkt_type_one = 0; integer pkt_type_two = 1; constraint C { x dist {pkt_type_one :/ 1, pkt_type_two :/2}; }

can be written as:


enum pkt_type_enum{PKT_TYPE_ONE=0,PKT_TYPE_TWO = 1}; rand integer x constraint C { x dist {PKT_TYPE_ONE :/ 1, PKT_TYPE_TWO :/ 2}; }

Use exact-size constants in constraints, for example, 8'h00 instead of 0. The use of decimal constants causes non-integer values to be promoted to integer values, which consume more time and memory

Randomization in Vera 5-110

Constraint Solver Diagnostics


The constraint solver diagnostics is used to analyze the solver performance and report constraints that contribute to a solver time-out or a halt at a randomize() call. The information provided in a solver diagnostic report aids users in writing efficient constraints. Note: For usage, structure of a diagnostic report, descriptions of diagnostic messages, and solutions for reported constraints are discussed in detail in the Constraint Solver Diagnostics application note. Synopsys strongly recommends that this application note be reviewed before using the diagnostic feature. To request a copy of the application note, email vera-support@synopsys.com. The constraint solver diagnostic feature can be enabled by a set of runtime options or per call options. By default, diagnostic information is displayed on standard I/O. There are two diagnostic modes: reactive and proactive: 1. In reactive mode, diagnostics are precise, and report specific constraints that slow down the solver performance. 2. In proactive mode, diagnostics serves as a lint tool, and report all possible constraint expressions that might impact the solver performance. There are two display modes for diagnostic information: non-verbose and verbose: 1. In non-verbose mode, the search space of all random variables to be solved in the current partition is printed only if there is at least one diagnostic message for the partition.

Randomization in Vera 5-111

2. In verbose mode, the search space of all random variables to be solved in the current partition is always printed.

Runtime Options
vera_enable_solver_diagnostics The + vera_enable_solver_diagnostics option enables the constraint solver diagnostics. The diagnostic mode is specified by the value argument. Syntax
+vera_enable_solver_dignostics=[value]

The optional value argument can be 0, 1, 2, 3 or 4.


Value
0 1 2 3 4

Mode
off (default) reactive, non-verbose proactive, non-verbose reactive, verbose proactive, verbose

vera_enable_solver_diagnostics_on_failure The +vera_enable_solver_diagnostics_on_failure option enables the constraint solver diagnostics and reports diagnostic information only when the solver times out. The diagnostic mode is specified by the value argument. Syntax
+vera_enable_solver_dignostics_on_failure=[value]

Randomization in Vera 5-112

The optional value argument can be 0, 1, or 2.


Value
0 1 2

Mode
off (default) reactive, non-verbose reactive, verbose

vera_solver_diagnostics_filename The +vera_solver_diagnostics_filename option specifies the name of the file for storing diagnostic information. The file is not created if no diagnostic message is reported. If this option is not specified, the diagnostic information is displayed on standard I/O. Syntax
+vera_solver_dignostics_filename=filename

Control of Diagnostic Reporting


Collection of diagnostic information starts from the beginning of a simulation when runtime options are used to enable the diagnostic feature. If per call options are used, collection starts when the randomize() function is called. Once enabled, collection of diagnostic information continues until the end of the simulation in all cases. The per call options enable display of diagnostic information for a single randomize() call only. The runtime options enable display for the entire simulation. For simulations involving a time consuming randomize() call, which can be identified, the following use model is recommended over using a per call only option:

Randomization in Vera 5-113

Enable collection of diagnostic information using the +vera_enable_solver_diagnostics_on_failure option Enable display of diagnostic information for the time consuming randomize() call using a per call option. The cumulative information collected from the beginning of simulation can lead to a more precise diagnostic report and better solutions.

For additional usage information, please refer to the Constraint Solver Diagnostics application note.

Solver Runtime Options to Control Memory and CPU Usage


Solver runtime options can be used to control memory consumption by the constraint solver and the CPU time consumption by a randomize() call. During a randomize() call, the constraint solver stores computation information that can be reused in subsequent randomize() calls. Reuse of the information improves the solver performance. However, storage of the computation information can consume a significant amount of memory when: The non random variables in randomize() calls change often or The following constructs are used: - unidirectional constraints - array constraints - function calls in constraints

Randomization in Vera 5-114

vera_solver_memory_limit The +vera_solver_memory_limit option is used to specify the maximum amount of memory for storing computation information generated by the constraint solver. There is no limit by default. This option is supported by the default solver only. Syntax
+vera_solver_memory_limit=<value>

The value argument specifies the memory limit in megabytes. When the limit is reached, the constraint solver maintains the computation information selectively. As a result, useful information may be dropped and the optimization of randomize() calls is limited. vera_solver_cpu_limit The +vera_solver_cpu_limit option specifies the time limit for issuing a solver timeout. There is no limit by default. This option is supported in all solver modes. Syntax
+vera_solver_cpu_limit=<value>

Value specifies the timeout limit in CPU seconds. When the limit is reached, the solver issues a timeout.

Compatibility with Vera Version 5.2 and older


Vera Version 6.0 provides major improvements for expressing and solving constraints. Constraint expressions can now be any expression, constraint solving is more reliable and robust, and

Randomization in Vera 5-115

random value distributions are more uniform. These improvements required modifications to existing randomization semantics that may change the random values previously computed by Vera. Constraint expressions now obey Verilog semantics regarding the width and type of intermediate expression values. There are two major aspects in which Vera 6.0 differs: - Previously, constraint expressions of the form
variable op expression

gave the operator higher precedence than normal. Now all constraint expressions, have Verilog precedence and associativity. Example: a < b < c previously grouped as a < (b < c). It now groups as (a < b) < c. Similarly, a < b ? c : d was previously grouped as a < (b ? c : d) and will now be grouped as (a < b) ? c:d Implication (=>) is a special case: it is right associative and high-precedence. - Expressions can be satisfied using wrap-around values. For example, a + b == 2 where a and b are four bits wide, can be satisfied by a = 9 and b = 9. That is, 9 + 9 = 18 (1 0010). Dropping the fifth bit leaves 2 (0010). - Relational operators are evaluated by extending the smaller operand to match the precision of the larger operand. Thus if a is two bits wide, and b is four bits wide, then the values a = 2'b11 and b = 4'b1100, satisfy the constraint a < b. The solver now chooses values with a uniform distribution. Previously, expressions such as x < y favored larger values on the right-hand-side of the operator. Values are now evenly

Randomization in Vera 5-116

distributed between x and y. In general, this means that the random values generated by previous Vera versions will not match the values generated in Vera versions 6.0 and later. Only 2-state logic is supported: X and Z logic values and their associated operators are not allowed. Accordingly, the ===, !==, =?=, and !?= operators are not supported because they operate on 4-state logic values. The randomize() method may not be overloaded. The pre_randomize() and post_randomize() methods of object members are now called concurrently with randomize(). The boundary() method is not supported in Vera 6.0 and later. Likewise, pre_boundary() and post_boundary() are not supported. The boundary methods will be revised in a later version. (See Pre-6.0 Boundary on page 5-118 for documentation of these methods.)

You can revert to the previous style of constraint expressions and solver semantics by specifying the random_compat option to the Vera compiler. This option must be specified for all source files:
vera -cmp -random_compat ... [file.vr]

The void syntax in conjunction with constraints is now deprecated, and is replaced with if or => syntax. Thus, this constraint:
enum PACKET_TYPE = CONTROL, DATA; class Packet { rand reg [31:0] dst; PACKET_TYPE payload_format; constraint c0 { dst == (payload_format == CONTROL) ? 48'h0180C2000001 : void; } }

Randomization in Vera 5-117

needs to be re-written either as:


constraint c0 { // supported on Vera 5.1 or later if (payload_format == CONTROL) dst == 48'h0180C2000001; }

or:
constraint c0 { // supported on Vera 6.0 or later (payload_format == CONTROL) => dst == 48'h0180C2000001 }

You can revert to the previous style of constraint expressions and solver semantics by specifying the random_compat option to the Vera compiler. This option must be specified for all source files:
vera -cmp -random_compat ... [file.vr]

If you are using random_compat, please consult a previous version of the Vera User Guide for information about pre-Version 6.0 constraint expressions and semantics. FIRST and NEXT specify which boundary condition to set.

Pre-6.0 Boundary
Veras boundary capabilities are used to generate values that match the upper and lower limits of a random variables valid value range. This is particularly useful because many design flaws occur at boundaries. Boundaries are generated when the system function boundary() is called.

Randomization in Vera 5-118

The syntax to call the boundary() function is:


function integer object_name.boundary(FIRST | NEXT);

object_name Is the name of the object on which the boundary() call is being made. Predefined Macros:

- FIRST sets the affected random values to their first boundary condition. - NEXT cycles through each subsequent boundary condition. Boundaries for random variables are determined by the constraints on a random variable. For instance, examine this constraint block:
class foo { rand integer a, b, c; constraint c1 { a>=10; a<=20; b>=0; b<=100; c in {1:15, 32:63}; } }

For this constraint block, a has the boundaries 10 and 20, b has the boundaries 0 and 100, and c has the boundaries 1, 15, 32, and 63. This results in 16 different boundary combinations that would be generated with the boundary() method. The boundary() method treats rand and randc variables the same way. Note that you can also use random variables within the constraints so that boundaries are dependent on random values. However, if the values of the right-hand side of a constraint change while the boundary() method is being invoked, the boundaries are

Randomization in Vera 5-119

determined by the values at the time of the function call. Subsequent changes to the boundaries do not affect the current call, but they will affect future calls. When the boundary() method is called, all random variables within the specified class instance are set to their boundaries. If the argument is set to FIRST, the first set of boundaries is used. If the argument is set to NEXT, the next set of boundaries in the sequence is used. The sequence of boundaries is influenced by a number of factors, including the order of variable declaration and the order they are named in the constraints. If there are random objects within the class instance calling boundary(), it also invokes object.boundary(). Thus, nested objects and extended classes are affected by calls to boundary(). Random variables declared as static are shared by all instance of the class in which they are declared. Each time the boundary() method is called, the variable is changed in every class instance. When the boundary() method is called, it returns a 1 (or OK) each time it successfully sets the random variables to their boundaries. If one or more variables cannot be set due to conflicting restraints, it returns a 0 (or FAIL). If the last set of boundaries has been set, it returns a 2 (or OK_LAST). If an object has no random variables anywhere in its inheritance hierarchy (no random variables or sub-objects) or if all of its random variables are inactive, the boundary() method returns a 3 (or NO_VARS). pre_boundary() The boundary() method makes calls to pre_boundary() and post_boundary() much in the same way that randomize() calls pre_randomize() and post_randomize().

Randomization in Vera 5-120

Syntax
task

object_name.pre_boundary(FIRST | NEXT);

object_name Is the name of the object on which the pre_boundary() call is being made. Predefined Macros: - FIRST sets the affected random values to their first boundary condition. - NEXT, cycles through each subsequent boundary condition. post_boundary() Syntax
task

object_name.post_boundary(FIRST | NEXT);

object_name Is the name of the object on which the post_boundary() call is being made. Predefined Macros: - FIRST sets the affected random values to their first boundary condition. - NEXT cycles through each subsequent boundary condition. boundary() This is an example of the boundary() system function:

Randomization in Vera 5-121

program b { integer success; my_object obj = new; success = obj.boundary(FIRST); while (success==OK) success = obj.boundary(NEXT); if (success!=OK_LAST) printf("Boundary problem (%0d)\n", success) }

This example defines the object obj. The random variables within obj are set to their initial boundaries with the first boundary() call. The while loop sets them to their other boundaries.

Random Sequence Generation


Veras sequence generation allows you to specify the syntax of valid sequences using BNF-like notation. Random sequences are ideal for generating streams of instructions for which it is easier to specify the syntax of valid streams than the constraints on specific values.

VSG Overview
The syntax for programming languages is often expressed in Backus Naur Form (BNF) or some derivative thereof. Parser generators use this BNF to define the language to be parsed. However, it is possible to reverse the process. Instead of using the BNF to check that existing code fits the correct syntax, the BNF can be used to assemble code fragments into syntactically correct code. The result is the generation of pseudo-random sequences of text, ranging from sequences of characters to syntactically and semantically correct assembly language programs.

Randomization in Vera 5-122

Veras implementation of a stream generator, the VSG, is defined by a set of rules and productions encapsulated in a randseq block. The general syntax to define a VSG code block is: randseq()
randseq (production_name) { production_definition1; production_definition2; ... production_definitionN; }

When the randseq block is executed, random production definitions are selected and streamed together to generate a random stream. How these definitions are generated is determined by the base elements included in the block. Any VSG code block is comprised of production definitions. Vera also provides weights, production controls, and production system functions to enhance production usage. Each of these VSG components is discussed in detail in subsequent sections.

Production Declaration
A language is defined in BNF by a set of production definitions. The syntax to define a production is:
production_name : production_list;

production_name Is the reference name of the production definition. production_list Is made up of one or more production_items.

Randomization in Vera 5-123

One or more production items makes up a production list. Production items are made of terminals and non-terminals. A terminal is an indivisible code element. It needs no further definition beyond the code block associated with it. Code blocks should be encapsulated in braces ({}). A non-terminal is an intermediate variable defined in terms of other terminals and non-terminals. If a production item is defined using non-terminals, those non-terminals must then be defined in terms of other non-terminals and terminals using the production definition construct. Ultimately, every non-terminal has to be broken down into its base terminal elements. Multiple production items specified in a production list can be separated by white space or by the or operator (|). Production items separated by white space indicate that the items are streamed together in sequence. Production items separated by the | operator force a random choice, which is made every time the production is called. This is a simple example illustrating the use of production items:
main top middle bottom : : : : top middle bottom; add | dec; popf | pushf; mov;

The main production definition is defined in terms of three non-terminals: top, middle, and bottom. When the call is made to this random sequence, top, middle, and bottom are evaluated, and their definitions are streamed together.

Randomization in Vera 5-124

The top, middle, and bottom production definitions are defined in terms of terminals. The | operator forces a choice to be made between the add and dec terminals and also between the popf and pushf terminals. This sequence block leads to these possible outcomes:
add add dec dec popf mov pushf mov popf mov pushf mov

This is an example of a full set of production definitions.


assembly_program: text_section data_section ; text_section: {printf(".text");} my_code ; data_section: {printf(".data");} data ; data : initialized_data | uninitialized_data ; my_code: { /* Vera code */} initialized_data: { /* Vera code */ } uninitialized_data: { /* Vera code */}

This example defines the production assembly_program in terms of text_section and data_section. The production text_section is then broken down to include the string .text and the non-terminal my_code. The production data_section is defined in terms of either of the two terminals initialized_data and uninitialized_data, the selection of which occurs when the randseq block is called. The resulting output is:
.text my_code output .data initialized_data output OR uninitialized_data output

Randomization in Vera 5-125

The my_code, initialized_data, and uninitialized_data outputs are determined by the code blocks associated with those productions.

Production Controls
Vera provides several mechanisms that can be used to control productions: weights for randomization, if-else statements, case statements, and repeat loops. This section includes: Weights for Randomization if-else Statements case Statements repeat Loops break Statement continue Statement

Weights for Randomization


Weights can be assigned to production items to change the probability that they are selected when the randseq block is called. Syntax
production_name : weight production_item;

Randomization in Vera 5-126

weight Must be in the form of &(expression) where the expression can be any valid OpenVera expression that returns a non-negative integer. Function calls can be made within the expression, but the expression must return a numeric value, or else a simulation error is generated. Assigning weights to a production item affects the probability that it is selected when the randseq block is called. Weight should only be assigned when a selection is forced with the | operator. The weight for each production item is evaluated when its production definition is executed. This allows you to change the weights dynamically throughout a sequence of calls to the same production. This is an example of a weighted production definition:
integer_instruction: &(3) add_instruction|&(i*2) sub_instruction;

This example defines the production integer_instruction in terms of the weighted production items add_instruction and sub_instruction. If i is 1 when the definition is executed, there is a 60% (3/5) chance that add_instruction is selected, and a 40% (2/5) chance that sub_instruction is selected.

if-else Statements
A production can be conditionally referenced using an if-else statement. The syntax to declare an if-else statement within a production definition is:
production_name :<if (condition) production_name else production_name>;

Randomization in Vera 5-127

condition Can be any valid Vera expression If the conditional evaluates to true, the first production item is selected. If it evaluates to false, the second production item is selected. The else statement can be omitted. If it is omitted, a false evaluation ignores the entire if statement. This is an example of a production definition that uses an if-else statement:
assembly_block : <if (nestingLevel > 10) seq_block else any_block>;

This example defines the production assembly_block. If the variable nestingLevel is greater than 10, the production item seq_block is selected. If nestingLevel is less than or equal to 10, any_block is selected.

case Statements
A general selection mechanism is provided by the case statement. The syntax to declare a case statement within a production definition is:
production_name : <case(primary_expression) case1_expression : production_name case2_expression : production_name ... caseN_expression : production_name [default : production_name > ;]

primary_expression Is evaluated. The value of the primary_expression is successively checked against each case_expression. When an exact match is found, the production corresponding to the matching case is executed, and control is passed to the
Randomization in Vera 5-128

production definition whose name is in the case item with the matching case expression. If other matches exist, they are not executed. If no case item value matches the evaluated primary expression and there is no default case, nothing happens. case_expression Can be any valid Vera expression or comma-separated list of expressions. Expressions separated by commas allow multiple expressions to share the same statement block A case statement must have at least one case item aside from the default case, which is optional. The default case must be the last item in a case statement. This is an example of a production definition using a case statement:
assembly_block : <case(i*3) 0 : seq_block 3 : loop_block default : any_block> ;

This example defines the production assembly_block with a case statement. The primary expression i*3 is evaluated, and a check is made against the case expressions. The corresponding production item is executed.

repeat Loops
The repeat loop is used to loop over a production a specified number of times. The syntax to declare a repeat loop within a production definition is:
production_name : <repeat (expression) production_name>;

Randomization in Vera 5-129

expression Can be any valid Vera expression that evaluates to a non-negative integer, including functions that return a numeric value. The expression is evaluated when the production definition is executed. The value specifies how many times the corresponding production item is executed. This is an example of a production definition using a repeat loop:
seq_block : <repeat (random() ) integer_instruction>;

This example defines the production seq_block, which repeats the production item integer_instruction a random number of times, depending on the value returned by the random() system function.

break Statement
The break statement is used to terminate a randseq block. Syntax
break;

A break statement can be executed from a code block within a production definition. When a break statement is executed, the randseq block terminates immediately and control is passed to the first line of code after the randseq block. This is an example of a production definition using a break statement

Randomization in Vera 5-130

SETUP_COUNTER: { integer regis = regFile.getRegister(); integer value = ADDI; nestingLevel++; if (nestingLevel == MAX_NESTING) break; ... } ;

This example executes the break if the conditional is satisfied. When the break is executed, control passes to the first line of code after the randseq block.

continue Statement
The continue statement is used to interrupt the execution of the current production. The execution continues on the next item in the production from which the call is made. Syntax
continue;

The continue statement passes control to the next production item in the production from which the call is made without executing any code in between. This is an example of a production definition using a continue statement:
LOOP_BLOCK: SETUP_COUNTER GEN_LABEL; SETUP_COUNTER: { integer regis = regFile.getRegister(); integer value = ADDI; nestingLevel++; if (nestingLevel == MAX_NESTING) continue; ... } ;

Randomization in Vera 5-131

This example first executes the SETUP_COUNTER production definition. When the continue is executed, the code after the continue is ignored and control passes to the GEN_LABEL production definition.

Passing Values Between Productions


Value passing within randseq blocks allows you to associate a data type with each production definition in order to pass values between production definitions. There are two components of value passing within randseq blocks: value declaration and value passing functions.

Value Declaration
To associate a data type and value with a given non-terminal production, you must declare the production using the prod declaration. The syntax to declare a production for value passing is:
prod data_type production_name;

data_type Can be integer, reg, string, enum, or any object. production_name Is the name of the production that is passing the value. Multiple productions can be declared in a single declaration statement, similar to variables. Vera performs strict type checking for passing values.

Randomization in Vera 5-132

Value Passing Functions


Vera provides two functions used to pass values in randseq blocks: prodset() and prodget(). The prodset() and prodget() system functions can be called from Vera code blocks within production definitions. prodset() The prodset() system task is used to set a value associated with a non-terminal. Syntax
task prodset (reg|integer|string|enum|obj value [, string production_name [, integer occurrence_number] ]);

value Is the value you want to pass. It must be of the same type as the prod declaration. It can be an integer, reg, string, enumerated type, or object. production_name Optionally specifies the name of the non-terminal production the value is being assigned to. If it is omitted, the production that the task is called in is assumed to be the production to the left of the colon (:). occurrence_number Optionally specifies which occurrence of the same production name receives the value. If the same production is referred to multiple times in the same definition, the first is 1, and the others are numbered sequentially. If it is omitted, it is assumed to be 1.

Randomization in Vera 5-133

The prodset() system task assigns the specified value to the specified occurrence of the non-terminal production. This value can be retrieved using the prodget() system function. prodget() The prodget() system function is used to retrieve values assigned to non-terminal productions. Syntax
function reg|integer|string|enum|obj prodget([string production_name [, integer occurrence_number] ]);

production_name Specifies the name of the non-terminal production the value has been assigned to. If it is omitted, the production that the task is called in is assumed to be the production to the left of the colon (:). occurrence_number Optionally specifies which occurrence of the same production name receives the value. If the same production is referred to multiple times in the same definition, the first is 1, and the others are numbered sequentially. If it is omitted, it is assumed to be 1. The prodget() system function returns the value assigned to the specified non-terminal production. Production values can only be associated with production names to the left of the code block where prodset() is called. If you assign a value to the production name to the left of the colon (:), the value is passed up to the calling production, where it can be retrieved.

Randomization in Vera 5-134

Calling prodget() on a production entry that has not been assigned returns an undefined value. You cannot set a value for a production that has not yet been executed. For example:
main : prod_a {prodset(5,prod_b,1); } prod_b /* invalid! */ main : prod_a {prodset(prod_a,2); } prod_b prod_a /* invalid! */ main : prod_a {integer tmp = prodget(prod_a); prodset(tmp+5,prod_a);} prod_b /* valid! */

This is an example of how to pass values within a randseq block:


program GenList { list vsgList; randseq() { prod list_node ELEMENT; TOP :{ vsgList = new(); } LIST END; LIST : &(10) LIST ELEMENT { list_node lnode = prodget ( ELEMENT, 1 ); vsgList.insert ( lnode ); printf ("last insert %0d\n", lnode.data); } | ELEMENT { list_node lnode = prodget ( ELEMENT, 1 ); vsgList.insert ( lnode ); printf ("inserting %0d \n", lnode.data); } ; ELEMENT : { list_node lnode = new(); prodset ( lnode ); printf ("new node is created %0d\n", lnode.data); } ; END : { vsgList.printAll(); } ; } }

Randomization in Vera 5-135

This example defines the list object vsgList. When the randseq block is entered, the TOP production is executed. First, a list object is instantiated. Then the LIST production is executed. The LIST production consists of a weighted LIST ELEMENT production and an ELEMENT production. If the LIST ELEMENT production is selected, the LIST production is called recursively and the ELEMENT production is postponed. The original selection between ELEMENT and LIST ELEMENT is then made again. The cycle continues until the ELEMENT production is selected. At that time, lnode is assigned a value via the prodset call in the ELEMENT production. That value is inserted into vsgList via the insert call in the code block. Finally, the previously unexecuted ELEMENT calls that had been postponed when LIST ELEMENT was selected are executed. Control is then passed back to the TOP production, which executes the END production. Note that each production is not assigned a single value. Instead, a stack of values can be assigned to a production, which are retrieved in order, through the dynamic execution of the production set.

Randomization in Vera 5-136

6
Data Packing and Unpacking 6
Transactors or Bus-Functional Models transfer data to or from the design under test via a bus. For example, in a networking testbench, a transactor on the transmit side will take packets (which are higher level data structures) generated from the packet generator and send them to the design under test in the form of a serial bit stream. In the same way, a transactor on the receive side will take the serial bit stream and transform it into the higher level data structure corresponding to the packet. Similarly, a transactor in a CPU testbench will generate a serial bit stream, corresponding to the higher level instruction, and send it to the device under test. Data packing consists of packing data fields into a serial bit stream and then unpacking the bit stream to re-form a data structure. Data packing is particularly useful for sending packets over serial communication streams and then converting them back to a packet structure.
Data Packing and Unpacking 6-1

This chapter includes the following sections: Pack and Unpack by System Functions Pack and Unpack by Class Methods

In addition to providing functions and methods for packing and unpacking data, there are also functions available for creating and verifying CRC codes for the data. For details of these functions, see the OpenVera LRM: Testbench manual.

Pack and Unpack by System Functions


The vera_pack() and vera_unpack() system functions are used for creating a data stream from global variables and variables in multiple objects (see chapter 13 of the OpenVera LRM: Testbench document for the syntax of these functions). These system functions can pack/ unpack a data stream into fixed-size arrays, dynamic arrays, associative arrays, or bit vectors. By default, the data stream is packed/unpacked in little endian format using vera_pack() and vera_unpack(). Vera provides two additional system functions, vera_pack_big_endian() and vera_unpack_big_endian(), for packing and unpacking in big endian format. In little-endian format, the least significant segment, or piece equal in size to the width of the data stream (or storage), is written first. If the segment does not fill the entire word in the storage, it is aligned towards the LSB or right side of the word.

Data Packing and Unpacking 6-2

In big-endian format, the most significant segment, or piece equal in size to the width of the data stream (or storage), is written first. If the segment does not fill the entire word in the storage, it is aligned towards the MSB or left side of the word.

Pack and Unpack by Class Methods


Data packing is integrated into the object-oriented framework of Vera. Vera defines several class methods that are used to pack and unpack data declared within a class. Vera also provides a set of attributes for class members that designate how data is to be packed and unpacked. This section includes: Identifying Data to Pack and Unpack Packing Attributes Packing Methods Unpacking Methods Details of Pack and Unpack

Identifying Data to Pack and Unpack


The first step in using object-orientated packing is to identify the variables to be packed. A variable can be marked for packing by prepending the packed keyword when the variable is declared.

Example 6-1
packed integer n;

Data Packing and Unpacking 6-3

Multiple variables can be marked for packing by creating a statement block using { }s preceded by packed.

Example 6-2
packed { integer n; reg[15:0] b; }

The data types you can pack and the number of bits for each type that are packed are as follows:
Data Type
integer reg[N -1:0] enum string

Bits required to pack


32

N
Minimum number of bits needed to represent all the enum values 8 x (strlen()+1 for NULL character)

Packing a null string causes a warning message to be issued, and one character (the NULL character) will be packed.

Packing Attributes
The packing method is controlled by one or more attributes immediately following the packed keyword. These attributes are: little_endian The least significant segment, or piece equal in size to the output array, is written first. If the segment does not fill the entire word in the output array, it is aligned towards the LSB, or right side of the word. The values of the right and index arguments are updated to reflect the first bit following the last bit written. The value of the left argument is reset to 0 when the write crosses a word boundary.

Data Packing and Unpacking 6-4

big_endian The most significant segment, or piece equal in size to the output array width, is written first. If the segment does not fill the entire word in the output array, it is aligned towards the MSB or left side of the word. The values of the left and index arguments are updated to reflect the first bit following the last bit written. The value of the left argument is reset to 0 when the write crosses a word boundary. bit_normal The data value is written to the output array unchanged. bit_reverse The data value bits are reversed before being written to the output array. These attributes can only be assigned to class variables; they cannot be assigned to class methods or constraints. If no attributes are specified, the default attributes are little_endian and bit_normal. When variable attributes are nested, the lowest level attribute overrides the higher level attributes. For example, in the following code i and n are packed bit_reverse, str is packed bit_normal, and k is unpacked:

Example 6-3
packed bit_reverse { integer i; bit_normal string str; unpacked { integer k; } integer n; }

Data Packing and Unpacking 6-5

When packing a data type that is a dynamic array, an additional attribute, dynamic_size, is required to specify the size of the array:

Example 6-4
packed [attribute] data_type array_name[*] dynamic_size size;

When packing a data type that is an associative array, an additional attribute, assoc_size, is required to specify the size of the array:

Example 6-5
packed [attribute] data_type array_name[*] assoc_size size;

Packing Methods
The input consists of a class object containing variables of type bit, integer, enum and string. The output is to an associative array organized as n words of m bits. The arguments specify the object to be packed, the index into the array and two values, left and right, which specify how many bits in the output word pointed to by index have been used, starting from the left and right of the word respectively. Data is written one segment at a time with the ordering and word alignment specified by the little_endian or big_endian attribute. The output array is filled starting from the specified index and leftmost unused bit for little_endian, or rightmost unused bit for big_endian. If all the bits in the current word are filled, left is zeroed for the big_endian case, or right for the little_endian case. At the end of the pack operation, index points to the last word written to. For big_endian data, the value of left is updated to specify how many

Data Packing and Unpacking 6-6

bits have been written to the left side of the word. For little_endian data, the value of right is updated to specify how many bits have been written to the right side of the word. Syntax
function integer object_name.pack(reg[N-1:0] array[], var integer index, var integer left, var integer right);

array
Specifies the array into which data is to be packed. The array is an associative array of bit width N.

index
Specifies the array index at which to start packing.

left
Specify the number of bits on the left to leave unchanged in array[index]. Normally, you initialize them to 0 before calling pack().

right
Specify the number of bits on the right to leave unchanged in array[index]. Normally, you initialize them to 0 before calling pack(). The pack() method returns the number of bits packed. It also updates index, left, and right so that they can be used as arguments to subsequent pack() calls when packing multiple objects into a single stream.

Data Packing and Unpacking 6-7

Example 6-6
integer nbits; integer offset = 0; integer left = 0; integer right = 0; reg [7:0] stream[]; nbits = packet_head.pack(stream, offset, left, right); nbits+ = packet_body.pack(stream, offset, left, right);

When the pack() method is called, it begins by packing the first member it encounters. If an objects handle is encountered, the pack() method of that class is invoked. Packing an object handle that is null produces a warning, and nothing is packed for that nested object; that object handle should also be null when the containing object is unpacked. If a nested objects handle is not null when it is packed, the handle should also be non-null before it is unpacked; unpacking does not call new to create objects.

Unpacking Methods
The unpacking methods are analogous to the packing methods. Syntax
function reg[63:0] object_name.unpack(scalar array, var reg[63:0] index, var reg[63:0] left, var reg[63:0] right);

The parameters have the same definitions as for pack(). The array parameter should be set to the array into which data was packed. The index, left, and right variables are normally initialized to 0. They are then updated with each call to unpack(). This allows you to unpack multiple objects from a single array. You should generally unpack multiple objects from one array in the same order in which they were packed. For example:
Data Packing and Unpacking 6-8

Example 6-7
x.pack(...); y.pack(...); z.pack(...); x.unpack(...); y.unpack(...); z.unpack(...);

Details of Pack and Unpack


The equivalent pseudo-code for the pack() method is:

Example 6-8
virtual function integer MyClass::pack(reg[N-1:0] array[], var integer offset, var integer left, var integer right, integer flag = 1) { integer nbits = 0; if (flag == 1) this.pre_pack(); nbits = super.pack (array, offset, left, right, 0); // code to pack the member variables of "this" that are marked packed // -- in order, including nested objects -- adding to nbits if (flag == 1) this.post_pack(); pack = nbits; } task MyClass::pre_pack() { super.pre_pack(); } task MyClass::post_pack() { super.post_pack(); }

Data Packing and Unpacking 6-9

Notice that the pack() method calls the pack() of its superclass before packing member variables of this class.Thus, the packing operation ultimately begins with the base class and works its way down the hierarchy, so that data associated with the base class is packed before data associated with its derived classes. Notice also that the flag parameter of super.pack is 0, so that it does not call pre_pack() and post_pack(). The unpack(), pre_unpack(), and post_unpack() methods follow this same pattern. Each of these methods must be public. If you override the pre-defined method, you must specify a particular bit width, which will be inherited by all the classs descendants.

Pack and Unpack Examples


The following are example of using the pack() and unpack() methods.

Example 6-9
#include <vera_defines.vrh> class Serial_Data_Type { static integer total_inst_count = 0; packed { rand reg [19:0] bit_data; string comment; } task new() { integer status; status = this.randomize(); if ( !status ) error ("Randomize failed!\n"); comment = psprintf("comment_%0d", total_inst_count) ; printf("inst = %-9d , data = %-25b comment = %0s\n", total_inst_count, bit_data, comment ); total_inst_count++ ; } // new }

Data Packing and Unpacking 6-10

program packed_test { Serial_Data_Type sdata_arr[5]; reg data_stream[]; // does not have to be byte stream integer i, offset, left, right; printf ("\n\nPacking data ...........\n"); offset = 0; left = 0; right = 0; for ( i = 0; i < 5; i++ ) { sdata_arr[i] = new(); void = sdata_arr[i].pack(data_stream, offset, left, right); } // for printf ("\n\nUnpacking data in order .....\n"); offset = 0; left = 0; right = 0; for ( i = 0; i < 5; i++ ) { void = sdata_arr[i].unpack ( data_stream, offset, left, right ); printf("inst = %-9d , data = %-25b comment = %0s\n", i, sdata_arr[i].bit_data,sdata_arr[i].comment); } // for // packed_test

Example 6-10
#include<vera_defines.vrh> class Packet{ packed rand packed rand packed rand packed rand

reg reg reg reg

[47:0] da; [47:0] sa; [15:0] type; [7:0] payload[5];

task print(){ integer i; printf("Packet da is %h printf("Packet sa is %h printf("Packet type is %h for(i=0;i<5;i++){ printf("Packet byte %0d is %h } } }

Data Packing and Unpacking 6-11

program main { Packet packet_to_be_sent; Packet packet_received; integer num_packet_bits =0, num_received_packet_bits; reg [7:0] packet_bytes[]; integer offset=0,left=0,right=0, i=0; //Generate packet with random fields packet_to_be_sent = new(); void = packet_to_be_sent.randomize(); printf("The following packet has been generated\n"); packet_to_be_sent.print(); // Pack packet into the stream of bytes, // represented by packet_bytes num_packet_bits = packet_to_be_sent.pack(packet_bytes, offset, left, right); printf("____________________________________________________"); printf("The above packet when driven across the Bus Functional\n"); printf("Model appears as the following stream of bytes\n"); for(i=0;i<num_packet_bits/8;i++){ printf("Packet byte %0d is %h\n",i,packet_bytes[i]); } //Now that packet has been packed into bits, it can easily be driven //across a bus functional model //............... //When the same stream of bytes is received at another bus functional //model it will need to be assembled into the corresponding higher // level packet, so we use the unpack method as follows printf("___________________________________________________\n"); printf("At the receiving Bus Functional Model, the above stream\n"); printf("of bytes is assembled into the following higher level packet\n"); offset=0;left=0;right=0; packet_received=new(); num_received_packet_bits = packet_received.unpack(packet_bytes,offset,left,right); printf("num_received_packet_bits is %d\n", num_received_packet_bits); packet_received.print();

Data Packing and Unpacking 6-12

} /*__________________________________ //Unpack reg [7:0] cap_packet[] int o=0; int l=0; int r=0; // unpack packet length = received_packet.unpack(cap_packet,o,l,r); // task to unpack packet into packet data structure task packet_check(reg [7:0] cap_packet[], int cap_length) { packet_ext1 received_packet; int o=0; int l=0; int r=0; int length; // allocate memory for new packet received_packet = new(); // unpack packet length = received_packet.unpack(cap_packet,o,l,r); */

The following shows the output:


Compilation errors: 0 ++---------------------------------------------------------------------++ || VERA System Verifier (TM) || || Version: 6.0.11 () -- Thu Nov 6 14:01:23 2003 || || Copyright (c) 1995-2002 by Synopsys, Inc. || || All Rights Reserved || || || || For support, send email to vera-support@synopsys.com || || || || This program is proprietary and confidential information of || || Synopsys Inc. and may be used and disclosed only as authorized in || || a license agreement controlling such use and disclosure. || ++---------------------------------------------------------------------++ The following packet has been generated Packet da is a13c05e23536 Packet sa is 33e2be7fe77d Packet type is 440b Packet byte 0 is df

Data Packing and Unpacking 6-13

Packet byte 1 is 40 Packet byte 2 is f7 Packet byte 3 is a6 Packet byte 4 is 1b ____________________________________________________________ The above packet when driven across the Bus Functional Model appears as the following stream of bytes Packet byte 0 is 36 Packet byte 1 is 35 Packet byte 2 is e2 Packet byte 3 is 05 Packet byte 4 is 3c Packet byte 5 is a1 Packet byte 6 is 7d Packet byte 7 is e7 Packet byte 8 is 7f Packet byte 9 is be Packet byte 10 is e2 Packet byte 11 is 33 Packet byte 12 is 0b Packet byte 13 is 44 Packet byte 14 is df Packet byte 15 is 40 Packet byte 16 is f7 Packet byte 17 is a6 Packet byte 18 is 1b __________________________________________________________ At the receiving Bus Functional Model, the above stream of bytes is assembled into the following higher level packet num_received_packet_bits is 152 Packet da is a13c05e23536 Packet sa is 33e2be7fe77d Packet type is 440b Packet byte 0 is df Packet byte 1 is 40 Packet byte 2 is f7 Packet byte 3 is a6 Packet byte 4 is 1b Vera: finish encountered at cycle 0 total mismatch: 0 vca_error: 0 fail(expected): 0 drive: 0 expect: 0 sample: 0 sync: 0

Data Packing and Unpacking 6-14

Example 6-11
class Instruction{ packed rand reg [3:0] opcode; packed rand reg [4:0] reg1; rand integer instr_type; packed rand reg [6:0] immediate; task print(){ printf(" Opcode is %h\n"); printf("Reg1 is %h\n"); printf("Immediate field is %h\n"); } } program main{ Instruction Instr; integer num_instruction_bits; reg [15:0] packed_instr[]; integer offset=0,left=0,right=0; Instr = new(); void = Instr.randomize(); printf("__________________________________________________\n"); printf("Instruction is as follows : \n"); Instr.print(); num_instruction_bits = Instr.pack(packed_instr,offset,left,right); printf("_________________________________________________\n"); printf("We now pack the instruction, so it can be placed in Instruction\n"); printf("Memory Packed Instruction is as %h\n"); printf("__________________________________________________\n"); Compilation errors: 0 ++---------------------------------------------------------------------++ || VERA System Verifier (TM) || || Version: 6.0.11 () -- Thu Nov 6 14:32:45 2003 || || Copyright (c) 1995-2002 by Synopsys, Inc. || || All Rights Reserved || || || || For support, send email to vera-support@synopsys.com || || || || This program is proprietary and confidential information of || || Synopsys Inc. and may be used and disclosed only as authorized in || || a license agreement controlling such use and disclosure. || ++---------------------------------------------------------------------++

Data Packing and Unpacking 6-15

_____________________________________________________________________ Instruction is as follows : Opcode is 6 Reg1 is 1c Immediate field is 62 ______________________________________________________________________ We now pack the instruction, so it can be placed in Instruction Memory Packed Instruction is as c5c6 ______________________________________________________________________ Vera: finish encountered at cycle 0 total mismatch: 0 vca_error: 0 fail(expected): 0 drive: 0 expect: 0 sample: 0 sync: 0

Data Packing and Unpacking 6-16

7
Functional Coverage
This chapter introduces Veras functional coverage analysis and discusses how it is used. Included here are these sections: Coverage Overview Defining Coverage Models Using Coverage Groups Cumulative and Instance-based Coverage Measuring Coverage Coverage Attributes Unified Coverage Reporting Coverage Data and Post-processing Tools Instance Names Predefined Coverage Group Tasks and Functions

Functional Coverage 7-1

Coverage Feedback: query()

Coverage Overview
As chip designs grow more complex and testing environments become increasingly sophisticated, emphasis has been placed on testing the chip completely. With hundreds of possible states in a system and thousands of possible transitions, the completeness of tests must be a primary focus of any verification tool. Traditional coverage models use a code coverage methodology. They check that specific lines of code are executed at some point in the simulation. This method has inherent flaws, however. For instance, you can be certain that a device entered states 1, 2 and 3, but you cannot be certain that the device transitioned from state 1 to 2 to 3 in sequence. Even such a simple example displays the limitations of code coverage methodology. With a sophisticated chip, such an approach is not adequate to ensure the integrity of the design. Vera supports a functional coverage system. This system is able to monitor all states and state transitions, as well as changes to variables and expressions. By setting up a number of monitor bins that correspond to states, transitions, and expression changes, Vera is able to track activity in the simulation. Each time a user-specified sampling event occurs, a counter associated with the bin is incremented. By establishing a bin for each state, state transition, and variable change that you want monitored, you can check the bin counter after the simulation to see how many activities occurred. It is, therefore, simple to check the degree of completeness of the testbench and simulation.

Functional Coverage 7-2

Vera further expands this basic functionality to include two analysis mechanisms: open-loop analysis and closed-loop analysis. Open-loop analysis monitors the bins during the simulation and writes a report at the end summarizing the results. Closed-loop analysis monitors the bins during the simulation and checks for areas of sparse coverage. This information is then used to drive subsequent test generation to ensure satisfactory coverage levels.

Defining Coverage Models Using Coverage Groups


The coverage_group construct encapsulates the specification of a coverage model or monitor. Each coverage_group specification has the following components: 1. coverage_points 2. cross products 3. sampling event 4. set of state and/or transition bins. A set of coverage points. Each coverage point can be a variable or a DUT signal to be sampled. A coverage point can also be an expression composed of variables and signals. The variables may be global, class members, or arguments passed to an instance of the coverage_group. A sampling event (a general event not just a Vera sync event) that is used for synchronizing the sampling of all coverage points.

Functional Coverage 7-3

Optionally, a set of state and/or transition bins that define a named equivalence class for a set of values or transitions associated with each coverage point. Optionally, cross products of subsets of the sampled coverage points (cross coverage).

The coverage_group construct is similar to an OpenVera class in that the definition is written once and is instantiated one or more times.The construct can be defined as a top-level (file scope) construct (referred to as standalone), or in a class (referred to as "embedded"). Once defined, standalone coverage is instantiated with the new() system call while embedded (contained) coverage groups are automatically instantiated with the containing object. The basic syntax for defining a coverage_group is:
coverage_group definition_name [(argument_list)] { sample_event_definition; [sample_definitions] [cross_definitions] [attribute_definitions] }

The syntax for defining an embedded coverage_group is:


class class_name { // class properties // coverage coverage_group definition_name .... (same as external). // constraints // methods }

For definitions, see Coverage Group in the OpenVera LRM. You can declare a coverage_group inside a class and then define it outside the class declaration block.

Functional Coverage 7-4

The syntax for defining a coverage_group outside the class is:


coverage_group class_name::coverage_grp_name [(arg_list)] { sample_event_definiton; [coverage__point_definitions] [cross_defintions] [attribute_definitions] }

Example 7-1 shows a standalone coverage_group definition and its instantiation.

Example 7-1
interface ifc{ input clk CLOCK; input sig1 PSAMPLE #-1; } coverage_group CovGroup{ sample_event = @ (posedge CLOCK); sample var1, ifc.sig1; sample s_exp(var1 + var2); } program covTest{ integer var1, var2; CovGroup cg = new(); }

In this example coverage_group CovGroup defines the coverage model for global variable var1, the signal ifc.sig1, and the expression composed of global variables var1 and var2. s_exp is the name that will be used to refer to the sampled expression. The two variables and the expression will be sampled upon every positive edge of the system clock. The coverage_group is instantiated using the new() system call.

Functional Coverage 7-5

Embedded Coverage Group


Embedded coverage groups simplify the monitoring of class properties by residing within the same scope as the class properties. This integrates coverage into OpenVeras object oriented paradigm, providing an intuitive and expressive mechanism for defining the coverage model associated with a class. The syntax for declaring a class with an embedded coverage_group is:
class class_name { ... coverage_group coverage_group_name{} ... }

For example, for class MyClass, defined in Example 7-2 below, if the user wants to cover members m_x, and m_y.

Example 7-2
class MyClass { bit [3:0] m_x; integer m_y; bit m_z; }

This can be accomplished this by using the coverage_group construct as follows:


class MyClass { bit [3:0] m_x; integer m_y; bit m_z; coverage_group cov1 { sample_event = @(posedge CLOCK); sample m_x, m_y; } }

Functional Coverage 7-6

Data members m_x and m_y will be sampled upon every positive edge of the system clock. A coverage_group construct that is embedded in a class can be instantiated in the body of the new task for the class.This eliminates the need for creating separate coverage objects for each instance of the class and binding them to the class data members that are to be covered. You can use an embedded coverage_group to define the coverage model for protected and private (local) data members as well as public members of a class. This way you do not need to jeopardize the data encapsulation of a class to define the coverage model for it. You can refer to all data members of a class within an embedded coverage_group. These members can either be sampled (used in the sample construct) or may be used in other places in the coverage_group construct, affecting the coverage specification or controlling coverage computation. A class can have more than one coverage_group. Example 7-3 shows two coverage_group constructs defined in class MyClass.

Example 7-3
class MyClass { bit [3:0] m_x; local bit m_z; coverage_group cov1 { sample_event = @(posedge CLOCK); sample m_x { state s0(0:7) if (m_z > 0); state s1(8:15); } } coverage_group cov2 { sample_event = wait_var(m_z); sample m_z; } }

Functional Coverage 7-7

In coverage_group cov1, public class member variable m_x is sampled at every positive edge of the system clock. State s0 defines a named bin for values 0 to 7 of the sampled variable. Local class member m_z controls when bin s0s hit count is incremented. State s0 is incremented only when the current value of m_z is non-zero. Note that in this example the two coverage groups are sampled on different events. Related items, therefore, can be grouped together, making it easier to view in reports. Also, attributes can be set differently for each group. For instance, collection can be disabled for one group, while enabled for another.

Instantiating Embedded Coverage Groups


Embedded coverage groups can be instantiated in one of two ways, either explicitly or implicitly. In addition, they can also be disabled using the null assignment statement. Explicit Instantiation Explicit instantiation of an embedded coverage group is done by the user, using the new assignment statement, and can only happen within the body of the new task for the embedding class. Embedded coverage groups which need to have arguments passed in must be explicitly instantiated in the new task of the embedding class. The Vera compiler issues an error if an embedded coverage group which needs arguments is not explicitly instantiated. The syntax for explicitly instantiating an embedded coverage group is:
coverage_group_name = new ([arguments]);

Functional Coverage 7-8

coverage_group_name
Is the name of the embedded coverage group.

arguments
Passed to the coverage group. Example 7-4 instantiates an embedded coverage group MyCov of class MyClass. A passed-in argument is used for setting the at_least attribute of the coverage group.

Example 7-4
class MyClass { bit [7:0] m_x; coverage_group MyCov (integer param1){ sample_event = @(posedge CLOCK); at_least = param1; sample m_x; } task new(integer p1) { m_x = 0; // Instantiate embedded coverage group MyCov MyCov = new(p1); } } program simple{ MyClass obj = new(4); @(posedge CLOCK); // ... }

An embedded coverage group (with or without arguments) can also be disabled using the null assignment statement. When an embedded coverage group is disabled, collection and reporting of coverage data for the coverage group is turned off.

Functional Coverage 7-9

The syntax for disabling an embedded coverage group is:


coverage_group_name = null;

coverage_group_name
This is the name of the embedded coverage group. Note that disabling an embedded coverage group using the above syntax can be done only within the body of the new task of the enclosing class.The instantiation or disabling of an embedded coverage group can be done inside nested blocks, like an if-then-else construct, so different instances of the class may have the embedded coverage groups as enabled or disabled. This is demonstrated in Example 7-5:

Example 7-5
class A { integer x; coverage_group cov1 { sample x; sample_event = @(posedge CLOCK); } task new(integer flag) { x = 0; // Coverage group can be instantiated // inside a conditional block if (flag) { // Instantiation using new, cov1 will // be instantiated. cov1 = new; } else { // Instantiation using null, cov1 will // not be active (not instantiated). //must be inside the constructor, that is // task new() cov1 = null; } } }

Functional Coverage 7-10

program test{ A obj1; A obj2; // Embedded cov_grp cov1 will be active for // this instance of A. obj1 = new(1); // Embedded cov_grp cov1 will not be active // for this instance of A obj2 = new(0); ... }

Implicit Instantiation Implicit instantiation of embedded coverage groups occurs under the following conditions. There is no user defined new task for the class, or the embedded coverage group is not initialized (disabled or instantiated) in the user defined new task for the class. The embedded coverage group requires no arguments.

Implicit instantiation means that the Vera compiler automatically instantiates the embedded coverage group as the first statement in the new task for the enclosing class. Users should be careful when availing of implicit instantiation as there may be some cases where implicit instantiation may lead to run time errors. Example 7-6 is of an embedded coverage_group that does not have any passed-in parameters, yet requires explicit instantiation in the new() task of the embedding class:

Functional Coverage 7-11

Example 7-6
class Helper{ event m_ev; // ... } class MyClass{ Helper m_obj; integer m_a; coverage_group Cov { sample m_a; sample_event = sync(ALL, m_obj.m_ev); } task new(){ m_obj = new; /* Instantiate embedded coverage_group here, after instantiating m_obj */ Cov = new; } }

In this example, coverage_group Cov is embedded under class MyClass. MyClass also declares an instance of the Helper class, called m_obj. The sample_event for the embedded coverage_group Cov refers to data member m_ev of m_obj. Therefore, the embedded coverage_group should not try to access m_obj.m_ev until m_obj has been instantiated. Otherwise a null object access would occur during Vera runtime. In order to avoid this, we instantiate embedded coverage_group Cov after instantiating m_obj in the task new.

Class and Coverage Group Definitions in Different Files


The definition of the coverage group can be specified in a different file than the one where the class definition, which specifies the coverage_group declaration, is present (see page 7-5).

Functional Coverage 7-12

// a.vr file class A { coverage_group Cov; }

You must compile the a.vr file to create a header file, a.vrh as follows:
% vera -cmp -H a.vr

The generated header files is:


////////////////////////////////////////////////////////// // Vera Header file created from a.vr ////////////////////////////////////////////////////////// #ifndef INC_A_VRH #define INC_A_VRH extern class A { coverage_group Cov ( ) {} } #endif

In a separate file, the coverage_group, Cov is defined. The a.vrh file must be included.
// cov.vr file #include "a.vrh" coverage_group A::Cov { statements_here }

At runtime, Vera resolves the coverage_group, Cov, declaration with the corresponding Cov definition. Note: You can manually create the above header file a.vrh by using the tool generated header file.

Functional Coverage 7-13

Scoping Rules
In general, the external definition of a coverage_group follows the same scoping rules as if the definition were embedded in the class. The following points should be noted when the coverage_group is defined in a different file than that of the class definition. The header file containing the class declaration (a.vrh in the above example) should be included in the file where coverage group is defined (as demonstrated in the above example) If a coverage_group definition consists of any global variables not defined in the same file, which contains this coverage_group definition, then the corresponding header file generated by the -H option of the compiler from the file where those global variables are defined must be included in the file containing the coverage_group definition.

Note: You can also directly create the header file containing the extern declaration for global variables.

Additional Header File Needed to Access Sample Point


If a coverage_group sample point or cross has to be accessed from some procedural code, then the header file generated from the file where the coverage_group is defined has to be included along with the header file generated from the file where the class is defined, inside the file where that sample point is accessed. Suppose you have a class A in A.vr file containing the declared coverage_group Cov. The class contains an integer i. The class is defined as given below:

Functional Coverage 7-14

class A { integer i; rand bit [3:0] vec1; rand bit [3:0] vec2; coverage_group cg () ; }

Generate the header file A.vrh using the command:


vera -cmp -H A.vr ////////////////////////////////////////////////////////// // Vera Header file created from A.vr ////////////////////////////////////////////////////////// #ifndef INC__TMP_TEMPLATE_FILE_VRH #define INC__TMP_TEMPLATE_FILE_VRH #include <vera_defines.vrh> extern class A { integer i; rand bit [3:0] vec1; rand bit [3:0] vec2; coverage_group cg () ; } #endif

Assume you have defined the coverage_group cg in file B.vr as follows:


#include "a.vrh" coverage_group a::cg { sample_event = @(posedge CLOCK) ; sample vec1{ state low (4'b0000) ; state med (4'b0001) ; state high (4'b0010) ; } // end sample vec1 sample vec2{ state low state med state high } // end sample

(4'b0000) ; (4'b0001) ; (4'b0010) ; vec2

cross cc (vec1, vec2) ; } // end cg

Functional Coverage 7-15

Note that the coverage_group cg in the B.vr file has a sample point, vec1. Suppose you want to call the pre-defined system task, set_coverage_goal(), on vec1. Further, this task is called in another file, say, main.vr. You must generate a header file from the file B.vr as given below:
vera -cmp -H B.vr ///////////////////////////////////////////////////////////////// // Vera Header file created from B.vr ///////////////////////////////////////////////////////////////// #ifndef INC__TMP_B_VRH #define INC__TMP_B_VRH #include "A.vrh" extern coverage_group A::cg () { sample vec1 ; sample vec2 ; cross cc ; } // end cg #endif

This header file B.vrh must be included in the file main.vr as shown below.
#include "B.vrh" program ext_cov_test { integer i ; A a ; a = new ; @(posedge CLOCK) ; a.cg.vec1.set_coverage_goal(1); a.cg.vec2.set_coverage_goal(2); a.cg.cc.set_coverage_goal(3); for(i=0; i<255; i++) { @(posedge CLOCK) ; void = a.randomize() ; } } // end program

Functional Coverage 7-16

Alternatively, you can modify the empty coverage declaration in the class header file generated A.vrh to include the sample points, in order to access the pre-defined functions of the coverage sample point. For example, the above header file A.vrh contains the class declaration with an empty coverage_group as shown below.
///////////////////////////////////////////////////////////////// // Vera Header file created from A.vr ///////////////////////////////////////////////////////////////// #ifndef INC__TMP_TEMPLATE_FILE_VRH #define INC__TMP_TEMPLATE_FILE_VRH #include <vera_defines.vrh> extern class A { integer i; rand bit [3:0] vec1; rand bit [3:0] vec2; coverage_group cg () ; } #endif

You can modify this header file to show that the coverage_group Cov consists of a sample, vec1. The resulting modified header file is:
///////////////////////////////////////////////////////////////// // Vera Header file created from a.vr ///////////////////////////////////////////////////////////////// #ifndef INC__TMP_TEMPLATE_FILE_VRH #define INC__TMP_TEMPLATE_FILE_VRH #include <vera_defines.vrh> extern class A { integer i; rand bit [3:0] vec1; rand bit [3:0] vec2; coverage_group cg () { sample vec1; } } #endif

Functional Coverage 7-17

In the .vr files where this header is included, you can access pre-defined functions for sample points. For example:
A a = new; a.B.vec1.set_coverage_goal();

Compiler reports mismatch between declaration and definition


When the coverage_group definition contains parameters, the compiler checks the data types in the declaration and definition of the coverage_group for consistency. An error is reported if they do not match. For example, if the declaration of the coverage_group is
class A{ coverage_group cov(sample bit[3:0] paramVar); ... }

and the definition is


coverage_group A::cov(sample integer paramVar){ ... }

the Vera compiler reports an error because the data type of the parameter in the declaration (bit) and the type in the definition (integer) are not the same. After having declared a coverage_group in a class, if you do not define it, then the Vera runtime will issue an error, when loading the corresponding .vro file.

Functional Coverage 7-18

Inheritance Does Not Override Coverage Groups


If a derived class and a base class have a coverage_group declared with the same name, the derived class coverage_group does not override the base class coverage_group. They are independent and not related to each other. Consider the example below:
// base.vr file class Base { coverage_group Cov; ... } // derived.vr class Derived extends Base { coverage_group Cov; ... }

Here, the coverage_group Cov in Base and the coverage_group Cov in Derived do not override each other. They are two different coverage groups. Note that the coverage report that gets generated from the coverage database reports them with the following names:
Base::Cov Derived::Cov

Multiple definitions of coverage groups is an error


Each coverage_group is defined exactly once. If a coverage_group is multiply defined, Vera flags an error at runtime.

Functional Coverage 7-19

External coverage definition is not possible in an aspect extension of a class


A coverage_group introduced in an aspect extension of a class must be defined inside the aspect class block itself. That is, a coverage_group cannot be declared inside the block but defined elsewhere. This is similar to the way methods of a class can be externally defined whereas new methods introduced in an aspect extension of the class should be defined inside the class block itself. For example the code given below results in an error at compile time since the aspect extension of class A defined as myaspect declares a coverage_group rather than defining it.
extends myaspect(A) { coverage_group asp_cov; }

Vera Scoping Rules in Coverage Groups


You can leverage Vera scoping rules for easy and simple definitions of coverage models without the need for passing variables as arguments to a coverage_group. You can specify coverage information for any Vera variable (or interface signal) that is visible in the scope that a coverage_group is defined in. This includes: Global variables Interface signals Static binds Global virtual ports

In addition, embedded coverage_groups can refer to:

Functional Coverage 7-20

Class data members Base class data members Public data members of member objects

Example 7-7 shows an embedded coverage_group that samples global variables, class data members, as well as an interface signal.

Example 7-7
#include "MyInterface.vrh" // Interface ifc1 extern integer g1; extern MemberClass { extern integer m_y; } extern MyBaseClass { extern integer m_z; } class MyClass extends MyBaseClass { integer m_x; MemberClass m_obj; coverage_group cov1() { sample_event = @(posedge CLOCK); sample m_x ; // Sample member of this class sample g1; // Sample global variable sample ifc1.sig; // Sample interface signal sample m_z; // Base class member sample m_obj.m_y; // Member of member object sample exp1(m_x + g1); // expression } }

Defining Sampled Coverage Points


The sample construct of a coverage_group defines coverage points that are monitored and binned by Vera. A coverage point can be a variable, a DUT signal or an expression composed of Vera variables, DUT signals and constants. In its simplest form, the sample construct has the following syntax:
sample coverage_point[, coverage_point] [conditional];

Functional Coverage 7-21

coverage_point
Is either an sample_expression or a sample_variable.

sample_expression
Is a Vera expression that needs to be sampled. The syntax for the sample_expression is:
sample_name (expression)

sample_name
Is a name associated with the expression.

expression
Is an OpenVera expression.

sample_variable
Is a Vera variable. To define state or transition bins for a sampled coverage point, or to specify the setting of a samples attributes, use the following syntax:
sample coverage_point [, coverage_point] [conditional] { [state_bin_definitions] [transition_bin_definitions] [attribute_definitions] }

Note: The conditional can only be if(OpenVera_expression)

coverage_point
Is either a variable or an expression as defined above.

Functional Coverage 7-22

state_bin_definitions
You can associate named bins with ranges of values of a sampled coverage point using the state, m_state, or bad_state constructs. See Overview of User Defined Bins for Coverage Points on page 7-31 for more details.

transition_bin_definitions
You can associate named bins with value transitions of a sampled coverage point using the trans, m_trans, or bad_trans constructs. See Overview of User Defined Bins for Coverage Points on page 7-31 for more details.

attribute_definitions
You can use attributes for controlling various aspects of a sample. The Coverage Attributes on page 7-80 section details the attributes that can be specified at the sample level, and their default values. You can specify an attributes value as follows:
attribute_name = value_expression;

where attribute_name is the name of the attribute, and value_expression is a Vera expression. See section Expressions within Coverage Group Definitions on page 7-75 for allowed expressions inside of coverage_group and coverage point definitions. When sampling an expression, the expression must be defined in the sample construct using the above syntax. You cannot sample an expression by passing in an expression as an argument to a coverage group. Sampled expressions must evaluate to an integral type of integer, bit vector, or enumerated type. They must not evaluate to an object, array, or string and must not contain a function or task call (either built-in or user-defined). They can refer to variables, signals, bind members, virtual port members that are visible in the scope that a coverage_group is defined and also to

Functional Coverage 7-23

parameters in the parameter list of a coverage_group. The parameters used in such expressions need not be prefixed by the sample keyword in the parameter list. Built-in methods such as query() and the attribute access methods, can be invoked on the sample_name associated with a sampled expression. Conditionals for Sample level definition Conditional statement can be added at the end of the sample level definitions. Conditional statements must be of the form if(OpenVera_expression). Functions other than get_cycle() and get_time() cannot be called in the conditional. When a conditional is attached to the sample level definition, all the bins for that sample is considered only if the conditional evaluates to true.
sample var1 if (open_vera_expression); //sample with autobinning sample var1 if (open_vera_expression), var2 if (open_vera_expression); //multiple samples in the same statement with different guard conditions sample var1 if (open_vera_expression) { // sample with user defined bins state s0(0); state s1(1); }

Functional Coverage 7-24

If a global variable or class data member is used in a condition, then the current (that is, value of the variable at sampling time) is used. There is no restriction in the use of coverage point names in a conditional associated with that coverage point or any other coverage point of the coverage_group. In the Passing Arguments to Coverage Groups on page 7-70 section we introduce the notion of passing arguments to a coverage_group.If a non-sampled, passed-by-value argument is used in a conditional statement, then the value of the argument at the time when the coverage_group is instantiation is used in the evaluation of the conditional. Reference to a sample_name in a guard (conditional) statement associated with a state or transition bin of a sample or cross is allowed. This is equivalent to using the corresponding sample expression in place of the sample_name.

Example 7-8
extern integer x, y; coverage_group Cov { sample sam2 (x * y); sample sam1 (x + y) { state s1 (0: 50) if (sam2 > 30); // same as //if (x*y > 30) } sample_event = @(posedge CLOCK); }

Auto Bin Creation


If you do not define any state or transition bins for a coverage point, Vera automatically creates state bins for you. This provides an easy-to-use mechanism for binning different values of a coverage point.

Functional Coverage 7-25

Vera follows the SystemVerilog style of auto bin creation to automatically create state bins for a coverage point. Use the following shorthand syntax (see Defining Sampled Coverage Points on page 7-21 for full definition) for defining the coverage point:
sample coverage_point [, coverage_point,...];

Note that you can refer to multiple coverage points in a single sample statement. In Example 7-9, Vera automatically creates state bins for coverage points m_x and m_y.

Example 7-9
class MyClass{ bit [0:7] m_x, m_y; coverage_group cov1 { sample_event = @(posedge CLOCK); sample m_x, m_y; } }

By default, Vera creates automatic state bins covering the entire range of values of the sample. You can control the number of automatic state bins created by using the auto_bin_max attribute (see page 7-80). The entire range of values of the sample is divided into N equal bins, where N is the value you specify via the auto_bin_max attribute. You can specify this attribute inside of a sample construct (applying to that coverage point only) or specify it at the coverage_group level for all coverage points of the group (see the Coverage Group Attributes section in the OpenVera LRM:Testbench manual for details).

Functional Coverage 7-26

For example, consider a sample that is a 4-bit variable and set auto_bin_max to 2. The possible range of values is 0 to 15. The tool creates two bins, with the associated ranges [0:7] and [8:15]. For 100% coverage, the simulation should result in values of the sample, uniformly distributed across the entire range. The following Vera code snippets show the effects of auto bin specification.
sample a { auto_bin_max = 7; }

or
// affects all samples coverage_group cg { auto_bin_max = 20; sample a, b; sample e (a + b) { } }

or
... sample a, b { auto_bin_max = 7; }// affects both a and b

Note: For enumerated types, auto_bin_max has no effect. Example 7-10 shows a fragment of Vera code that defines a coverage_group with automatically created bins for global sampled variables m_x and m_y. The auto_bin_max attribute has been used to limit the number automatically created state bins to 2.

Functional Coverage 7-27

Example 7-10
bit [3:0] m_x, m_j; coverage_group cov1 { sample_event = @(posedge CLOCK); sample m_x, m_y; auto_bin_max = 2; // max of 2 auto-created bins } ... m_x = 12; m_y = 3; @(posedge CLOCK); m_x = 1; m_y = 8; @(posedge CLOCK); m_x = 5; m_y = 4; @(posedge CLOCK);

The Table 7-1 shows the automatically created bins when the coverage_group is first instantiated :

Table 7-1 Automatically generated bins for sample m_x


Bin Name
auto[0:7] auto[8:15]

Hit Count
0 0

Table 7-2 Automatically generated bins for sample m_y


Bin Name
auto[0:7] auto[8:15]

Hit Count
0 0

Functional Coverage 7-28

The Table 7-3 shows the automatically created bins (and their hit counts) after the first @(posedge CLOCK):

Table 7-3 Hit count for the bins after the first @(posedge CLOCK)
Sampled Variable
m_x

Bin Name
auto[0:7] auto[8:15]

Hit Count
0 1 1 0

m_y

auto[0:7] auto[8:15]

The Table 7-4 shows the automatically created bins (and their hit counts) after the second @(posedge CLOCK):

Table 7-4 Hit count of the bins after the second @(posedge CLOCK)
Sampled Variable
m_x

Bin Name
auto[0:7] auto[8:15]

Hit Count
1 1 1 1

m_y

auto[0:7] auto[8:15]

The Table 7-5 shows the automatically created bins (and their hit counts) after third (and final) @(posedge CLOCK):

Table 7-5 Automatically generated bins after the third @(posedge CLOCK)
Sampled Variable
m_x

Bin Name
auto[0:7] auto[8:15]

Hit Count
2 1 2 1

m_y

auto[0:7] auto[8:15]

Functional Coverage 7-29

Automatically Generated Bins for Enumerated Types When a coverage point is of an enumerated type, Vera automatically creates state bins for all the enumerated values of the coverage point. In this case, the auto_bin_max attribute does not affect the number of automatically created bins. A coverage point which is an expression is considered to be of an enumerated type, if all the operands are of the same enumerated type. Otherwise the type of the coverage point expression depends on the type and width of the sampled expression. In Example 7-11, coverage_group covType samples the global variable sParam which is of the enumerated type, cellType.

Example 7-11
enum cellType = blue, red, green; extern cellType sParam; coverage_group covType { sample_event = wait_var(sParam); sample sParam; auto_bin_max = 2; // Does not affect the number // auto-bins for sParam }

Vera will automatically creates three state bins even though the auto_bin_max attribute has been set to 2. Example 7-11 is shorthand for explicitly typing out the following coverage_group:

Example 7-12
coverage_group covType { sample_event = wait_var(sParam); sample sParam{ state s_blue(blue); // sParam == blue state s_red(red); // sParam == red state s_green(green); // sParam == green } }

Functional Coverage 7-30

Overview of User Defined Bins for Coverage Points


Coverage bins can be explicitly defined for each of the coverage points. This way you can create named bins for states and/or value transitions of a coverage point. A state bin (using the state or m_state construct) defines a named bin for a set of values of a coverage point. A transition bin (using trans or m_trans constructs) defines a named bin for one or more sequence of values associated with a coverage point. The syntax for defining explicit state and/or transition bins uses ranges of values to define states and transitions. Example 7-13 defines two state bins and a transition bin for the sampled variable port_number of coverage_group MyCov. The variable port_number (assumed to be global) is sampled every time it changes.

Example 7-13
coverage_group MyCov () { sample_event = wait_var(port_number)async; // Sample every time port_number changes sample port_number { state s0(0:7); state s1(8:15); trans t1("s0"->"s1"); } }

State bin s0 is associated with values of the sampled variable port_number between 0 and 7. State s1 is associated with values of port_number between 8 and 15. Transition bin t1 is associated with any value transition (single) of sampled variable port_number from 0-7 to 8-15. For instance, when port_number changes from 0 to 8 or 0 to14 transition bin t1s hit count is incremented.

Functional Coverage 7-31

Multi-State and Multi-Transition Specification You can use the m_state (short for multi-state) and m_trans constructs to create multiple bins for a range of values. Vera automatically creates a bin for each of the values in the range. The following m_state creates 8 bins. Each bin corresponds to one of the values in the range 0 to 7.
m_state ms(0:7);

Each of the automatically created bins is prefixed with the name used in the m_state construct. In the example above, Vera creates state bins ms_0, ms_1, ms_2, ms_3, ms_4, ms_5, ms_6, and ms_7. State bin ms_0 is the state bin associated with the coverage point having value 0. In the following example we use the m_trans construct to automatically create four transition bins associated with the transitions 0->3, 0->4, 1->3, and 1->4 of a coverage point.
m_trans ms(0:1->3:4);

In this example transition bin ms:0->3 is associated with the transition of the coverage point from value 0 to value 3. Multi-state (m_state) and multi-transition (m_trans) specifications are useful for explicitly controlling the range of values that you are interested in binning, and creating individual bins for each of the values in the range. In the above m_state example we are only interested in the coverage of the coverage point when its value falls within the range 0 to 7, and would like to know how many times the coverage point takes on the values of interest. An alternative would have been to avoid explicit definition of the m_state and use Veras auto-binning capabilities. However, the initial values of the coverage points may be outside of the range of interest, causing Vera to create bins that are not interesting.
Functional Coverage 7-32

In general, explicit state and transition specifications help you define and refine the shape of your coverage space. However, you should be wary of defining m_state and m_trans specifications for a large range of values, since this can affect Veras performance. The m_state and m_trans bin specifications do not expand beyond 4096 bins. Wildcard State and Transition Definitions By default, a state or transition bin definition that uses an x is only matched if the coverage point has an x in that bit position (the semantics are similar to the === operator). The wildcard state and wildcard trans bin definitions cause the Vera coverage engine to consider an x in the bin definition as a wildcard. In the following example, the state bin s5 increments when the coverage point is either 1100, 1101, 1110, or 1111.
wildcard state s5(4b11xx);

Bad States and Transitions Illegal states (values) of a coverage point can be defined using the bad_state statement as follows:
bad_state state_name (range_definition) [conditional ];

Illegal or bad states are those values of the coverage point that, when sampled, result in a verification error. Illegal value transitions of a coverage point can be defined using the bad_trans statement as follows:
bad_trans trans_name (transition_specification)[conditional];

Illegal or bad transitions are those value transitions of the coverage point that result in a verification error.
Functional Coverage 7-33

All States and Not State A special case of a state bin definition uses the all specification:
state state_bin_name (all);

This statement indicates that Vera will create a bin for each of sampled values of the coverage point (or increment the bin hit count). Similarly, a special case of a transition bin definition uses the all specification:
trans transition_bin_name (all);

This statement creates a transition bin for every 2 state transition of the coverage point. Note that the all state or transition specifications are intended for debugging coverage information only. The bin hit counts associated with the individual bins created for all state or transitions do not affect coverage numbers. More important, if you use state(all) or trans(all), a significant amount of memory may be used if the number of unique values of the coverage point is large. Finally, individual bins for state(all) or trans(all) are created (and their hit count incremented) even if the sampled value matches other user-defined bins. Another special case of a state definition uses the not state specification:
state state_bin_name (not state);

When using this construct, all values not recorded by other states will increment the bin-hit counter for state_bin_name.

Functional Coverage 7-34

Using Conditionals in Bin Definitions You can add a conditional statement at the end of any state or transition bin specification so long as they are user-defined bins. Conditional statements must be of the form if(OpenVera_expression). Functions other than get_cycle() and get_time() cannot be called in the conditional. When a conditional is attached to a bin definition, the bin is only updated (that is, its hit count is incremented) if the conditional evaluates to true and the value of the coverage point matches the bins specification. In the following example, state s0 is hit (that is, its hit count is incremented) only if the coverage points value is between 0 and 7 and value of variable g_var is greater than 0.
state s0(0:7) if (g_var > 0);

Note that in the above example g_var could be any variable visible to the coverage_group based on Veras normal scoping rules (for example involving global variables, class data members, etc.). If a global variable or class data member is used in a condition, then the current (that is, value of the variable at sampling time) is used. There is no restriction in the use of coverage point names in a conditional associated with that coverage point or any other coverage point of the coverage_group. In the Passing Arguments to Coverage Groups on page 7-70 section we introduce the notion of passing arguments to a coverage_group.If a non-sampled, passed-by-value argument is used in a state or transition bins conditional, then the value of the argument at the time when the coverage_group is instantiation is used in the evaluation of the conditional.

Functional Coverage 7-35

In the following sections we will describe the syntax for defining state and transition bins in detail.

User-defined States for Coverage Points


State definitions associate a named bin with a range of values of a coverage point. States are defined inside of the sample construct. Syntax
state state_bin_name (state_specification) [conditional];

state_specification
Is a list of elements (separated by commas) that are matched against the current value of the coverage point. In a state declaration, a single state or multiple states are associated with a monitor bin by means of a state specification. For the current cycle, any matches increment the bin counter by one. Each element of the state specification is a value range specification in one of the following formats:

expression
A counter is added to the bin when the state of the coverage point matches the expression exactly. x or z must match exactly.

low:high
A counter is added to the bin when the state of the coverage point matches any value in the range from low to high.

Functional Coverage 7-36

low:high:step:repeat
This creates multiple ranges. The first block ranges from low to high. The second block ranges from (high+step) to (2*high-low+step). New blocks are generated repeat times. For example: 2:5:10:3 would produce states {2, 3, 4, 5,15, 16, 17, 18, 28, 29, 30, 31} (2, 3, 4, 5) --> (15, 16, 17, 18) -->(28, 29, 30, 31) Complex state specifications can be generated by separating multiple formats with commas.

Example 7-14
state bin1 (8b0000_01XX, 8:10, 15:17:7:2);

This state specification will increment the bin counter if any of the specifications matches the state of the coverage point. In this example, a counter will be added to the bin if: The state of the coverage point matches 8b0000_01XX exactly. The state of the coverage point falls in the range of 8 to 10. The state of the coverage point falls in the range of 15 to 17 and 24 to 26.

Note: x and z are not allowed in repeated range statements. It is important to note that state specifications are evaluated only once, at the time the coverage object is instantiated. While the state of the coverage point is being monitored, the state specification remains constant.

Functional Coverage 7-37

m_state The m_state state declaration is used to declare multiple state bins up to a maximum of 4096 bins. Syntax
m_state state_bin_name (exp1:exp2);

state_bin_name
Is the base name of the state bins being created.

exp
Can be any valid coverage expression. You cannot call functions in the expressions. The expressions can include variables. When the m_state declaration is used, multiple state bins are created, covering all the values in the range. The expressions are evaluated when the coverage object is instantiated. For example:
m_state s1 (2:4);

This example creates these bins with their respective state values: State Bin Name s1_2 s1_3 s1_4 State Value 2 3 4

If no bin name is specified, the same example yields these bin names and values: State Bin Name s_2 s_3 s_4 State Value 2 3 4

Functional Coverage 7-38

All States and Not State A special case of a state declaration uses the all state specification. The all state specification should only be used when debugging coverage information. It does not contribute to the coverage statistics for the enclosing sample and coverage_group.
state binname (all);

This statement indicates that Vera should create a unique state bin for each sampled value of the coverage point. The generated state bins are named:
binname_value

where value is the value of the coverage point. Note: If you use state(all), a significant amount of memory is used if the number of sampled and unique states is large. Another special case of a state declaration uses the not state specification:
state state_bin_name (not state);

Using this construct, all values not recorded by other states increment the counter for state_bin_name. State Bin Names Bins can be assigned explicit names, or the Vera compiler can generate implicit names. The Vera compiler generates implicit bin names based on the state specification. The general format is always prefaced by s_. The following characters are converted to underscores (_): comma (,), colon (:), slash (/), dash (-), plus (+),

Functional Coverage 7-39

asterisk (*), and period (.). The following characters are ignored when the bin name is generated: double quote ("), brackets ([]), parentheses (()), dollar sign ($), caret (^), back slash (\), and braces ({}). For example, see Table 7-6:

Table 7-6 State Expression and Implicit Bin Name


State Expression
(5,7,9,11) (15:37) (base*10+3) (all)

Implicit Bin Name


s_5_7_9_11 s_15_37 s_base_10_3 binname_ value (see above)

Conditionals in State Definitions The conditional can only be if(OpenVera_expression) You can add conditional statements at the end of any state declaration. Functions other than get_cycle() and get_time() cannot be called in the conditional. If there is a conditional statement attached to the state declaration, the bin counter will be incremented only if both the condition is true and the state of the coverage point matches the state specification at the same time. Note: You do not need to pass variables used in coverage conditionals as arguments to the coverage object, if the variables are visible in the scope where the coverage_group is defined. If you use a passed-by-value parameter of the coverage_group in a conditional, then the value of the parameter at the time that the coverage_group is instantiated is used. If you use a passed-by-reference parameter of the coverage_group in a conditional, then the value of the parameter at the time that the conditional is evaluated (at every sample point) is used. See the

Functional Coverage 7-40

Passing Arguments to Coverage Groups on page 7-70 for more details. A sample name associated with a sampled expression can also be used in the conditional expression.

Example 7-15
state jmp_ins (8b0000_01XX, 8:10, 15:17:7:2) if (test == ON);

This state declaration creates the bin jmp_ins. The bin counter is incremented when both the state of the coverage point matches the specification and the conditional is true. Wildcard State Declarations By default, a bit with a value of x must match a sampled value of x for a state bin counter to be incremented. The wildcard keyword treats the x value as a wildcard in the state declarations:
wildcard state state_bin_name(state_specification);

Example 7-16
wildcard state sw(4b11xx);

The state bin increments for 1100,1101,1110, and 1111. Multiple State Bin Declarations A state declaration can have multiple bins declared on a single line as follows:
state b0 (0), b1 (1), b2 (2);

In this example, b0, b1, and b2 are separate state bins, each with its own state specification. Further, multiple state declarations are allowed, and the same value can be associated with multiple state bins.

Functional Coverage 7-41

Example 7-17
state b0 (0:10); state b1 (10:20);

Value 10 is associated with both bin b0 and bin b1.

User-defined Illegal States for Coverage Points


Illegal state definitions associate illegal states with a coverage point being sampled by a coverage_group. Illegal states of a coverage point are defined inside of the sample construct.) Syntax
bad_state error_bin_name (state_specification) [conditional];

Illegal or bad states are those states in the design that, when entered, result in verification errors. The state specification can be any expression or combination of expressions as in the state declarations. However, it is often useful to define every state that is not in the state declarations as a bad state. To use that definition of bad states, you can use the not state specification:
bad_state error_bin_name (not state);

This statement increments the specified bin counter every time the state of the coverage point matches a value not defined in the state declarations and a runtime verification error is issued. If you do not specify an error bin name, the implicit name is s_not_state. If you want to specify multiple bad states, you can use the m_bad_state declaration.

Functional Coverage 7-42

Syntax
m_bad_state error_bin_name (exp1:exp2);

When the m_bad_state declaration is used, a bin for each value in the range is created. If no bin name is specified, the same naming conventions for m_state are used.

User-defined Transitions for Coverage Points


Transition definitions associate value transitions with a coverage point. Transitions are defined inside the sample construct of a coverage_group. Syntax
trans trans_bin_name (transition_sequence_list) [conditional];

trans_bin_name
This is the name of the transition bin.

transition_sequence_list
A transition sequence list is a comma-separated list of transition sequences. Defining Transition Sequences Each transition sequence defines value transitions of the coverage point. A transition sequence has the following form:
value_range_set -> value_range_set -> ... -> value_range_set

A value range set is made up of one or more value ranges. A value range can be one of: any of the value range specifiers used for defining a state,
Functional Coverage 7-43

a state bin name, specified in a state declaration and enclosed in double quotes, Note: When specifying a state bin name, the value ranges specified for that state are used for matching the transition sequence. The guard condition for that state bin is ignored.

a Perl regular expression matching a state bin name, enclosed in double quotes

If a value range set has more than one value range, the set must be enclosed by brackets ([]), and the members separated by commas:

Example 7-18
trans trans_bin_name (["jms_ins", br:xor, "jmp[0-9]+"] -> [ 15:20:2:100]);

This example defines a complex value transition. The specified bin counter is incremented when any of the following occurs: The state of the coverage point changes from a value defined by state jms_ins to a value that falls in the repeated range defined by [15:20:2:100]. The state of the coverage point changes from a value in the range from br to xor to a value that falls in the repeated range defined by [15:20:2:100]. The state of the coverage point changes from a value defined in any state bin that begins with jmp and ends with at least one digit to a value that falls in the repeated range defined by [15:20:2:100].

Functional Coverage 7-44

If all value range sets in a transition sequence are matched in order, then the transition monitor bin is incremented. For a transition sequence with more than two value range sets, if only one of the transitions (that is, from one range set to another) is observed, the monitor bin is not incremented. m_trans The m_trans transition declaration is used to declare multiple transition bins up to a maximum of 4096 bins. Syntax
m_trans trans_bin_name (exp1:exp2 -> exp3:exp4);

trans_bin_name
Is the base name of the transition bins being created.

exp
Can be any valid coverage expression. You cannot call functions in the expressions. The expressions can include variables that are visible in the scope that the coverage_group is being defined in. When the m_trans declaration is used, multiple transition bins are created, covering all the transitions in the specified ranges. Each set of expressions specifies a range. A bin is created for each permutation of valid values.

Example 7-19
m_trans t1 (2:3 -> 4:5);

This example creates these bins with their respective transitions:

Functional Coverage 7-45

Transition Bin NameTransition t1:2->4 t1:2->5 t1:3->4 t1:3->5 2 to 4 2 to 5 3 to 4 3 to 5

If no bin name is specified, the same example yields these bin names and values: Transition Bin Name t_s_2_3_s_4_5:2->4 t_s_2_3_s_4_5:2->5 t_s_2_3_s_4_5:3->4 t_s_2_3_s_4_5:3->5 All Trans and Not Trans A special case for transition bins is the all transition argument:
trans trans_bin_name (all);

Transition 2 to 4 2 to 5 3 to 4 3 to 5

In this case, Vera creates and tracks a transition bin for every twostate value transition of the coverage point. Note: The automatically created bins associated with the all transition specification do not contribute to the coverage statistics of the enclosing sample and coverage_group constructs. Note: If you use trans(all), a significant amount of memory is used if the number of sampled and unique transitions is large.

Functional Coverage 7-46

Another special case of a transition declaration uses the not trans specification:
trans trans_bin_name (not trans);

When using this construct, undefined transitions are recorded without a verification error being printed. Transition Bin Names Bins can be assigned explicit names, or the Vera compiler can generate implicit names. The Vera compiler generates implicit bin names based on the value transition. The general format is always prefaced by t_. The following characters are converted to underscores (_): comma (,), colon (:), slash (/), dash (-), plus (+), asterisk (*), and period (.). The following characters are ignored when the bin name is generated: double quote (""), brackets ([]), angled brackets (<>), parentheses (()), dollar sign ($), caret (^), back slash (\), and braces ({}). For example: Transition Expression (5 -> 7 -> 9 -> 11) (15:37 -> 2:5) ([base*10, 9] -> "jmp[0-9]+") (all) Conditional You can add conditional statements at the end of any transition declaration. Conditional statements must be of the form if(OpenVera_expression). Functions other than get_cycle() and get_time() cannot be called in the conditional. If there is a conditional statement attached to the transition declaration, the bin Implicit Bin Name t_5_7_9_11 t_15_37_2_5 t_base_10_9_jmp0_9_ t_all

Functional Coverage 7-47

counter will be incremented only if both the condition is true and the state of the coverage point makes the specified transition at the same time. Note: You do not need to pass variables used in coverage conditionals as arguments to the coverage object. However, you must declare those variables using the extern construct within the main program. If you use a passed-by-value parameter of the coverage_group in a conditional, then the value of the parameter at time that the coverage_group is instantiated is used. If you use a passed-by-reference parameter of the coverage_group in a conditional, then the value of the parameter at the time that the conditional is evaluated (at every sample point) is used. See the Passing Arguments to Coverage Groups on page 7-70 section for more details.

Example 7-20
trans jmp_ins (8:10 -> 15:17:7:2) if (test == ON);

This transition declaration creates the bin jmp_ins. The bin counter is incremented when both the state of the coverage point makes the specified transition and the conditional is true. If you specify a sequence of transitions, the conditional is only evaluated during the final transition. Wildcard Transition Declarations By default, a bit with a value of x must match a sampled value of x for a transition bin counter to be incremented. The wildcard keyword treats the x value as a wildcard in the transition declarations:
wildcard trans trans_bin_name(value_transitions);

Functional Coverage 7-48

Example 7-21
wildcard trans tw(2b0x -> 2b1x);

The transition bin increments for transitions from: 00 -> 10 00 -> 11 01 -> 10 01 -> 11 Defining Multiple Transitions in One Statement A transition declaration can have multiple bins declared on a single line:
trans b0 (0 -> 1), b1 (1 -> 2), b2 (2 -> 3);

In this example, b0, b1, and b2 are separate transition bins, each with its own transition specification. Repeated Transition Values You can specify the number of times a particular value is to be repeated in a transition sequence using these constructs:
[.constant.] [.min_constant:max_constant.]

constant
Must be an unsigned integer constant. It may not be an expression that evaluates to a constant. Using the first construct, the transition value preceding the constant must be repeated a fixed number of times. For example, these transition declarations are equivalent:
Functional Coverage 7-49

trans t1(1 -> 2[.3.] -> 3); trans t1 (1 -> 2 -> 2 -> 2 -> 3);

Using the second construct, the transition value preceding the constant must be repeated at least min_constant times and not more than max_constant times. For example:
trans t1(1 -> 2[.1:3.] -> 3);

This transition declaration creates a single monitor bin that is equivalent to these transition declarations:
trans t1(1 -> 2 -> 3); trans t2(1 -> 2 -> 2 -> 3); trans t3(1 ->2 -> 2 -> 2 -> 3);

It is important to note that the first example uses a single monitor bin to count any of the valid transitions, whereas the second example uses three separate bins to monitor the same transitions.

User-defined Illegal Transitions for Samples


Illegal transition definitions associate an illegal transition with a coverage point. Illegal Transitions are defined inside the sample construct of a coverage_group. Syntax
bad_trans trans_bin_name (transition_sequence_list) conditional;

The Defining Transition Sequences on page 7-43 section describes the syntax for defining transition sequence lists. In some circumstances it is useful to monitor all transitions that have not been defined in other transition bins.

Functional Coverage 7-50

For such instances, Vera uses the not trans argument:


trans trans_bin_name (not trans);

The counter associated with the specified bin will be incremented every time a transition occurs that is not explicitly defined in any of the transition declarations for the coverage point. If you do not specify the bin name, the implicit name is t_not_trans. The not trans modifier applies only to single transitions between two values (or two value range sets). It does not apply to larger transition sequences. So, if you define a bad_trans using not trans then you must make sure that all valid single transitions are covered in one of the transition bins. If you want to specify multiple bad transitions, you can use the m_bad_trans declaration. Syntax
m_bad_trans error_bin_name (exp1:exp2 -> exp3:exp4);

When the m_bad_trans declaration is used, a bin for each transition is created. If no bin name is specified, the same naming conventions for m_trans are used.

Functional Coverage 7-51

Cross Coverage
You can define cross coverage by crossing subsets of the coverage points being sampled by a coverage_group. Crosses of coverage points of a coverage_group can be specified using the cross construct. In its simplest form the cross construct has the following form:
cross cross_name (coverage_point, coverage _point, ...);

In this case Vera automatically creates bins for the cross product of state or transition bins covering the complete range of values for the sample or coverage point. The integration of cross coverage into the coverage model specification ensures a tighter and easier to understand semantics. Crosses are specified up front in the coverage_group specification and refer to the coverage points in the same coverage_group. All crosses (cross constructs) and coverage points (sample constructs) are sampled using the same sampling event (sample_event of the coverage_group). In Example 7-22, the embedded coverage_group cov1 samples two data members of the embedding class MyClass (data members m_x and m_y), and a global variable g_var1. The coverage_group defines a cross named cc1 for crossing sampled variables m_y and g_var1. Since the example does not define any state or transitions for the sampled variables, Vera automatically creates state bins covering the complete range of values for the sampled variables. Cross cc1 will include bins associated with the cross product of the automatically generated bins for the sampled variables m_y and g_var1.

Functional Coverage 7-52

Example 7-22
extern bit [1:0] g_var1; class MyClass { bit [3:0] m_x, m_y; bit m_z; coverage_group cov1 { sample_event = @(posedge CLOCK); sample m_x, m_y, g_var1; cross cc1(m_y, g_var1); auto_bin_max = 8; } task new(){ m_x = 4b0000; m_y = 4b0000; m_z = 1b0; } } program test{ bit [3:0] g_var1 = 4b0000; MyClass Obj1 = new; @(posedge CLOCK); Obj1.m_y = 2; g_var1 = 1; @(posedge CLOCK); Obj.m_y = 0; @(posedge CLOCK); }

Coverage Report
Summary for variable m_x Expected Covered Percent Automatically Generated Bins 8 1 12.50 Automatically Generated Bins for m_x Uncovered bins name count at least [auto[2:3] - auto[14:15]] -1 (7 bins) Covered bins name count at least auto[0:1] 2 1 ------------------------------------------------------------------------------

Functional Coverage 7-53

Summary for variable m_y Expected Covered Percent Automatically Generated Bins 8 2 25.00 Automatically Generated Bins for m_y Uncovered bins name count at least [auto[4:5] - auto[14:15]] -1 (6 bins) Covered bins name count at least auto[0:1] 1 1 auto[2:3] 1 1 --------------------------------------------------------------------Summary for variable g_var1 Expected Covered Percent Automatically Generated Bins 8 1 12.50 Automatically Generated Bins for g_var1 Uncovered bins name count at least [auto[2:3] - auto[14:15]] -1 (7 bins) Covered bins name count at least auto[0:1] 2 1 --------------------------------------------------------------------Summary for cross cc1 Samples crossed: m_y g_var1 Expected Covered Percent Missing Automatically Generated Cross Bins 64 2 3.12 62 Automatically Generated Cross Bins for cc1 Uncovered bins m_y g_var1 count at least [auto[0:1] - auto[2:3]] [auto[2:3] - auto[14:15]] -1 (14 bins) [auto[4:5] - auto[14:15]] [auto[0:1] - auto[14:15]] -1 (48 bins) Covered bins m_y g_var1 count at least auto[2:3] auto[0:1] 1 1 auto[0:1] auto[0:1] 1 1

Functional Coverage 7-54

Vera creates automatic state and cross bins as shown in the report. After the first sampling event, Vera updates the hit count for the automatically generated state bins auto[0:1] of state m_y (since m_y has the value 0f 0) and auto[0:1] of state g_var1 (since g_var1 has the value of 0). In turn their corresponding cross bin (auto[0:1], auto[0:1]) of the cross cc1 is hit. Each of these three bins has a hit count of 1. After the second sampling event, Vera updates the hit count for the automatic state bin auto[2:3] for sampled variable m_y (since m_y has the value of 2) with hit count of 1, and increments the hit count of bin auto[0:1] of sampled variable g_var1 with hit count of 2. In turn the corresponding cross bin (auto[2:3], auto[0:1]) of the cross cc1 is also updated with hit count of 1. Conditionals for Cross level definition Conditional statement can be added at the end of the Cross level definitions. Conditional statements must be of the form if(OpenVera_expression). Functions other than get_cycle() and get_time() cannot be called in the conditional. When a conditional is attached to the Cross level definition, all the bins for that cross is considered only if the conditional evaluates to true.
cross cc1(cp1, cp2) if (open_vera_expression); // cross with no user defined bins cross cc1(cp1, cp2) if (open_vera_expression){ // cross with user defined bins state cc1_s1(binsof(cp1) intersect {2}); bad_state cc1_b1(binsof(cp1) intersect {4}); }

Functional Coverage 7-55

If a global variable or class data member is used in a condition, then the current (that is, value of the variable at sampling time) is used. There is no restriction in the use of coverage point names in a conditional associated with that coverage point or any other coverage point of the coverage_group. In the Passing Arguments to Coverage Groups on page 7-70 section we introduce the notion of passing arguments to a coverage_group.If a non-sampled, passed-by-value argument is used in a conditional statement, then the value of the argument at the time when the coverage_group is instantiation is used in the evaluation of the conditional.

User-Defined Cross Coverage Bins


You can define and name your own cross coverage bins and use them to: Define illegal cross products Define cross products that should be ignored Combine cross products into a single named bin or equivalence class

You can use Vera binsof expressions for easy and concise specification of cross coverage bins. The syntax for a cross construct that defines cross coverage bins is:
cross cross_name (coverage_point, coverage_point...) { [cross_bin_definitions] [attribute_definitions] }

Functional Coverage 7-56

cross_name
This is the name of the cross. You can use this name to access the cross (query or set information about the cross) in the testbench.

cross_bin_definitions
You can use Vera expressions for defining named cross coverage bins. To define a cross coverage bin that combines several cross products into single named bin or equivalence class, use the following syntax:
state state_name ((select_expression)[logical_operator (select_expression)]) [ if (expression) ];

- select_expression: Subset of bins_expression.


([!]binsof(bins_expression) [intersect {value_range_list}])

- bins_expression: The expression that identifies the bins to be specified for a cover point identifier.
cover_point_identifier [.bins_identifier]

cover_point_identifier: The name of a cover point. bins_identifier: The name of bin. - value_range_list: A list of value ranges. - logical_operator: Is && or ||. If the expression for the state evaluates to true, then the hit count of the cross coverage bin state name is incremented. You can optionally specify a conditional for the cross coverage state. In that case the bin is only hit only if both the expression that defines the bin as well as the conditional evaluate to true. To define cross products that should not be considered for coverage calculations, use the ignored keyword.
Functional Coverage 7-57

Syntax
ignored state_name ((select_expression)[logical_operator (select_expression)]) [ if (expression) ];

If the expression for the ignored cross coverage bin evaluates to true, then the enclosing cross is skipped, and none of its bins are updated. To define cross products that are illegal and should not occur, use the bad_state keyword Syntax
bad_state state_name ((select_expression)[logical_operator (select_expression)]) [ if (expression) ];

If the expression for the bad_state evaluates to true, then Vera issues a verification error.

attribute_definitions
You can use attributes for controlling various aspects of a cross. The Coverage Attributes on page 7-80 section details the attributes that can be specified at the cross level, as well as their default values. You can specify an attributes value as follows:
attribute_name = value_expression;

where attribute_name is the name of the attribute, and value_expression is a Vera expression. See section Expressions within Coverage Group Definitions on page 7-75 for expressions allowed inside of coverage_group and coverage point definitions. Precedence Semantics for User-Defined Cross Bins You can have several user-defined cross coverage bins of each kind (that is, state, bad_state, and ignored). The question that arises is how should Vera behave when your cross construct includes

Functional Coverage 7-58

user-defined cross coverage bins of each kind. Moreover, what should the precedence semantics be when the expression for more than one of the user-defined cross coverage bins evaluates to true? When a cross construct includes one or more state, bad_state, and ignored bins, Vera uses the following precedence semantics: If any of the illegal bins (bad_state) is matched (expression evaluates to true), then Vera issues a verification error. Otherwise, if any of the ignored bins (ignore) is matched, Vera does not update or add any bins and proceeds to the next cross (if any). Otherwise, each of the user-defined (non-illegal, non-ignored) cross coverage bins (state) that match (expression evaluates to true) are updated (that is, their hit count is incremented). Otherwise, Vera, if necessary, updates the automatic cross product bin and the hit count of that bin. The bin is associated with the state and/or transition bins that are hit in each coverage point involved in the cross.

Example 7-23
extern i, j, k; coverage_group cov1 { sample_event = @(posedge CLOCK); sample i, j, k; cross cc1 (i,j) { state MyCrossBin(binsof(i) intersect {0:4}); ignored IgnoredCrossProds(binsof(i) intersect {4:7} && binsof(j) intersect {2:6}); bad_state BadCrossProds((binsof(i) intersect {4}) && (binsof(j) intersect {2})); } }

Functional Coverage 7-59

The following discussion analyzes Example 7-23 for different values of sampled variables i, j, and k using the precedence semantics described above. If i is 4 and j is 2, then the expressions for all three bins evaluate to true, according to the precedence semantics described above. Vera issues a verification error, and does not proceed to update the hit count for MyCrossBin. Vera does not ignore the cross either, even though the expression for IgnoredCrossProds also evaluates to true. This is because bad_states have the highest precedence. If i is 4 and j is 5, the expressions for both IgnoredCrossProd and MyCrossBin (but not BadCrossProds) evaluate to true. In this case, Vera gives higher precedence to the ignored cross coverage state, and skips cross MyCross. The hit count for MyCrossBin is not updated. If i is 4 and j is 8, then MyCrossBin is the only user-defined bin whose expression evaluates to true. That bins hit count is incremented. Finally, if i is 5 and j is 7, then none of user-defined bin expressions evaluate to true. In that case Vera automatically updates the cross product bin (auto[5:5], auto[7:7]) for cross MyCross and the hit count is incremented. Examples of Embedded Coverage Groups with User-Defined Cross Coverage Bins In the following code fragment, an embedded coverage_group that defines a cross cc1 for sampled variables m_y, m_z, and g_var1.

Functional Coverage 7-60

Example 7-24
class MyClass { ... coverage_group cov1 { sample_event = @(posedge CLOCK); sample m_x, m_y, g_var1; cross cc1(m_y, m_z, g_var1) { bad_state bad1((binsof(m_y) intersect {0:12}) && (binsof(m_z) intersect {0}) || (binsof(m_y) intersect {7:15}) && (binsof(g_var1) intersect {0})); ignored ig1 ((binsof(m_y) intersect {0:15}) && (binsof(m_z) intersect {0})); } } }

The example uses a Vera expression for defining an illegal (bad_state) cross product named bad1. If the expression evaluates to true at the time that the cross is sampled, Vera issues a verification error. A Vera expression is also used to define the set of cross products that should be ignored by coverage. This is accomplished by using the ignore statement in conjunction with a Vera expression that evaluates to true when m_y is between the value 0 and 15, and m_z is 0. Vera will not update any cross product bins when the ignore state is satisfied. If the illegal and ignored cross states are not satisfied, Vera proceeds to update the hit count for the corresponding automatic cross bins. In Example 7-25, an embedded coverage_group defines a cross cc1 for sampled variables m_y, m_z, and g_var1.

Functional Coverage 7-61

Example 7-25
extern bit [0:4] g_var1; class MyClass { bit [0:4] m_x, m_y; coverage_group cov1 { sample_event = @(posedge CLOCK); sample m_x, m_y, g_var1; cross cc1(m_y, m_z, g_var1) { state s1 ((binsof(m_y) intersect {0}) && (binsof(m_z) intersect {2})); } } }

At each positive edge of the system clock, if the sampled values of m_y and m_z are 0 and 2 respectively, Vera increments the hit count for bin s1 of cross cc1 (regardless of the sampled value for g_var1). For example, for following set of sampled values, Vera will increment state s1: - m_y = 0, m_z = 2, g_var1 = 7 - m_y = 0, m_z = 2, g_var1 = 1 When the coverage points are sampled, if the expression associated with a user-defined cross state does not evaluate to true, Vera updates the corresponding automatically generated cross product bin for the state and/or transitions that are hit in each coverage point. In Example 7-25, when the sampled value of m_y, m_z, and g_var1 are 1, 2, and 7 respectively, Vera updates the automatic bin (auto[1:1], auto[2;2], auto[7:7]) for the cross product of cc1. Valid Expressions for Defining Cross Coverage Bins Although Vera allows for the use of expressions in a cross coverage bin specification, there are certain kinds of expressions that are not allowed and flagged as semantic errors by the Vera compiler.

Functional Coverage 7-62

Validity of expressions used in cross coverage bin specification is governed by the following three rules: Since tasks and functions can be blocking, you cannot use task or function calls. A sample name associated with a sampled expression can be used in the expression, provided it is present in the list of samples for the cross.

Sample Event
A sampling event expression must be specified in the coverage group definition. This sampling event is used for all instantiations of a coverage definition. An event expression does not need to be specified when instantiating the coverage_group. The sampling event expression allows you to control when the object takes a sample. Coverage objects can be triggered on clock edges, signal edges, variable changes, sync events and OVA events.

Types of Sampling Events


Clock and Signal Edges. Coverage objects can be sampled on clock or signal edges as per the sample_event_definition. When the specified edge occurs, the object is sampled. Syntax
sample_event = @([specified_edge] interface_signal | CLOCK);

In Example 7-26, all instances of coverage group cov1 are sampled at the positive edge of the system clock.

Functional Coverage 7-63

Example 7-26
coverage_group cov1{ sample_event = @(posedge CLOCK); sample g_var; }

Variable Changes. Coverage objects can be sampled when variables change value using the wait_var() system task. When the value of a variable change occurs, the object is sampled. Syntax
sample_event = wait_var(some_openvera_variable);

In Example 7-27, the embedded coverage group cov1 in all instances of the class MyClass will be sampled upon the change in the value of the xref data member.

Example 7-27
class MyClass { integer xref; coverage_group cov1 { sample_event = wait_var(xref); sample xref; } }

Sync Events. Coverage objects can be sampled on sync events. When the sync is unblocked, the object is triggered. Syntax
sample_event = sync(ALL|ANY, some_Vera_event);

In Example 7-28, the embedded coverage group cov1 in all instances of the class MyClass will be sampled when the event ev1 is triggered.

Functional Coverage 7-64

Example 7-28
extern Event ev1; class MyClass { integer xref; coverage_group cov1 { sample_event = sync(ALL, ev1); sample xref; } }

If the sample event, is a sync, then the event needs to be triggered. If the event is in the ON state (that is, some Vera thread performed a trigger(ON) statement) sampling will not occur. Note that coverage objects waiting on a sync event do not count towards the count for HAND_SHAKE triggers. That is, if the sync event is triggered in the HAND_SHAKE mode, all coverage objects waiting on that event are triggered. These do not count towards the HAND_SHAKE. An additional explicit Vera thread waiting on that sync event will also be triggered. OVA Events. Coverage objects can be sampled on OVA events. When the OVA event occurs in the DUT, the Wait() member task on the OVA object unblocks (see chapter 12 for description of Wait() in the OpenVera LRM: Testbench book).

Example 7-29
sample_event = ova_object.Wait();

Where ova_object is an instance of an OVAEvent (see OVAEvent Class in chapter 12 of the OpenVera LRM: Testbench book). In Example 7-30, the class MyClass has a member variable which is an OVAEvent class object. The embedded coverage group cov1 is sampled when the OVA event attached to the OVAEvent class object fires.

Functional Coverage 7-65

Example 7-30
class MyClass { integer port_num; OVAEvent portEvent; coverage_group cov1 { sample_event = portEvent.Wait() sample port_number; } }

General Task Calls. In the most general case, the sampling event expression can be any task call. This can be used when more elaborate event sequences are needed to trigger sampling of coverage objects. In Example 7-31, the coverage object is sampled a certain number of clock cycles after the triggering of an OVA event. The number of clock cycles is specified by a parameter.

Example 7-31
task CoverageTrigger1(integer numCycles){ integer i; globalOVAEvent.Wait(); for (i=0;i<numCycles;i++){ @(posedge CLOCK); } } coverage_group cov1 (integer numCyclesAfterOVAEvent){ sample_event = CoverageTrigger1(numCyclesAfterOVAEvent); sample xref; }

Note: The task is called by the Vera Coverage system. It should not have any side-effects such as changing the value of variables. Unpredictable behavior could result if the task has side effects of any kind. The task should block. A task which does not block at all will result in only a sampling of the coverage object in a Vera cycle.

Functional Coverage 7-66

Default Synchronous Behavior of Sampling Event. The default behavior of sampling events is to sample the coverage object in a synchronous fashion (that is, The coverage object is sampled at the end of the simulation cycle after all Vera processing that can change variables is complete). Also, the coverage object is sampled at most once per simulation cycle even if the sampling event triggers more than once. Optional Async Behavior of Sampling Event. Optionally, the async attribute can be used with the sample event specification. When this attribute is used, the coverage object is sampled immediately upon the triggering of the sampling event. If the sampling event fires more than once in the simulation cycle, the coverage object will be sampled more than once as well (that is, it will be sampled once per trigger). When the async attribute is used with a sample event that is a wait_var or Vera sync event, then the coverage object is sampled immediately upon the triggering of the event. When the async attribute is used with a sample event that is a synchronization on a signal or clock edge or an OVA event, then the coverage object is sampled at the beginning of Vera processing instead of at the end of Vera processing. In Example 7-32, the embedded coverage group cov1 in all instances of the class MyClass will be sampled immediately upon the Vera event global_event being triggered.

Example 7-32
class MyClass{ integer xref; coverage_group cov1{ sample_event = sync(ALL, global_event) async;

Functional Coverage 7-67

sample xref; } }

Variables and Signals Referenced in Sample Event Expressions. Use of Global Variables and Signals The sample event expression can reference global variables and signals. In this case, all instantiations of the coverage group definition will have the same sampling event. In Example 7-33, all instances of the coverage group covType will be sampled upon the posedge of the ifc.clk signal.

Example 7-33
#include "my_interface.vrh" coverage_group covType (){ sample_event = @(posedge ifc.clk); sample g_var; }

Use of Class Member Variables The sample event expression of an embedded coverage group can reference member variables of the nesting class. In Example 7-34, the embedded coverage group covType will be sampled upon every change in value of the member variable m_e of the nesting class object (that is, the coverage object obj1.covType will be sampled upon the change in value of obj1.m_e, and the coverage object obj2.covType will be sampled upon the change in value of obj2.m_e.class).

Example 7-34
MyClass{ integer m_e; coverage_group covType{ sample_event = wait_var(m_e); sample m_e;

Functional Coverage 7-68

} } ... ... MyClass obj1 = new; MyClass obj2 = new;

Use of Passed-in Parameters The sample event expression can reference parameters passed-in to the coverage group. This feature can be used to set a different sampling event for each instance of a coverage group. In Example 7-35, coverage object cov1 is sampled upon every change to the gWait variable and coverage object cov2 will be sampled upon every change of the gAcc variable. Note that the parameter is passed as a var parameter, since we want to track all changes to its value.

Functional Coverage 7-69

Example 7-35
coverage_group covType (var integer waitInt) { sample_event = wait_var(waitInt); sample g_var; } integer gWait, gAcc; ... covType cov1 = new(gWait); covType cov2 = new(gAcc);

Passing Arguments to Coverage Groups


What if your coverage model cuts across your class abstraction and all of the elements of your coverage model do not reside in the same class? For example, you may want to cross variables from different classes or cross a data member from one instance with a data member from another instance of the same class. You can pass arguments to a coverage_group in order to address this need. The coverage_group construct optionally allows for the declaration of formal parameters. Actual arguments are passed in to the coverage_group instance as parameters to the new task call. You can define three kinds of parameters in the coverage_groups definition: sampled, passed-by-value, and passed-by-reference. Sampled Parameters Sampled parameters are preceded by the sample keyword in the formal parameter list of the coverage_group definition. They are really treated like a constant var argument passed to a task. In Example 7-36, coverage_group MyCov defines a sampled parameter paramVar that is sampled at every positive edge of the system clock.

Functional Coverage 7-70

Example 7-36
coverage_group MyCov(sample bit[3:0] paramVar){ sample_event = @(posedge CLOCK); // Sample event sample paramVar; // Passed-in sample parameter } ... program Example { bit [3:0] gVar; MyCov cov1; ... cov1 = new(gVar); ... }

In the above example, variable gVar is passed as an argument to instance cov1 of the coverage_group when the new task is called. The coverage_group instance therefore samples variable gVar at every positive edge of the system clock. Non-Sampled Parameters Passed by Value Parameters that are not preceded by any keywords in the formal parameter list of a coverage_group definition are considered as pass-by-value (that is, having a constant value). When a pass-by-value argument is passed to a coverage_group instance, the value of the passed argument at the time the new task is called is used by the coverage_group instance. Such arguments can be used in state and transition bin specifications for defining ranges of values associated with a bin. They can be used in defining states associated with the cross of coverage points (for example, illegal and ignored bin specifications of crosses). In Example 7-37, coverage_group MyCov defines two parameters that are passed by value (param and param2). It also samples a global variable (gVar) at the positive edge of the system clock.

Functional Coverage 7-71

Example 7-37
coverage_group MyCov(integer param, integer param2){ sample_event = @(posedge CLOCK); sample gVar{ state s1 (0:param); state s2 (param+1 : 15); state condState (16 : 31) if (param2 > 4); } } ... program Example { bit [4:0] gVar; integer gP1, gP2; MyCov cov1; ... gP1 = 7; gP2 = 3; cov1 = new(gP1, gP2); ... }

In Example 7-37, instance cov1 of MyCov is instantiated with actual arguments gP1 (parameter param) and gP2 (parameter param2) having the values 7 and 3 respectively at the time that cov1 is instantiated. The values of gP1 and gP2 at the time of instantiation of cov1 imply the following: State s1 is associated with 0 <= gVar1 <= 7 State s2 is associated with 8 <= gVar1 <= 15

state condState will not be hit. This is because the value of the second parameter of the coverage_group instance cov1 (argument gP2) is 3 at the time of instantiation, causing the conditional to evaluate to false at every sample.

Functional Coverage 7-72

Non-Sampled Parameters Passed by Reference Parameters that are preceded by the var keyword in the parameter list of the coverage_group definition are passed-by-reference. Passed-by-reference arguments are really considered constant references since the Vera coverage engine does not attempt to modify their value. If a pass-by-reference parameter is used in a conditional (of a state or transition bin specification), the current value of the actual argument passed to the instance of the coverage_group is used every time the instance samples. If a pass-by-reference parameter is used in defining the range of values associated with a state or transition bin, then the value of the actual argument at the time the coverage_group is instantiated is used. This is because Vera requires that the range of values associated with a state or transition bin to be defined at the time that the coverage_group is instantiated, and remain constant at every sample. The range of values associated with each state or transition bin cannot be dynamic (change at every sample point). In Example 7-38 coverage_group MyCov samples global variable gVar at every positive edge of the system clock. It defines a passed-by-value parameter param and a passed-by-reference parameter param2. Parameter param is used in the definition of state bins s1 and s2. Parameter param2 is used in the conditional associated with state bin condState.

Functional Coverage 7-73

Example 7-38
coverage_group MyCov(integer param, var integer param2){ sample_event = @(posedge CLOCK); sample gVar{ state s1 (0:param), state s2 (param+1 : 15); state condState (16 : 31) if (param2 > 4); } } ... program Examplehes g{ bit [4:0] gVar; integer gP1, gP2; MyCov cov1; ... gP1 = 7; cov1 = new(gP1, gP2); //instantiate cov1 and pass arguments ... gP2 = 3; @(posedge CLOCK); // 1st sampling event after instantiation gP2 = 5; @(posedge CLOCK); // 2nd sampling event after instantiation ... }

When instantiating coverage_group instance cov1, arguments gP1 and gP2 are passed (for the parameters param and param2 respectively). At the time of instantiation gP1 has a value of 7. This implies that state s1 of coverage_group instance cov1 is associated with 0 <= gVar1 <= 7. Similarly state s2 of coverage_group instance cov1 is associated with 8 <= gVar1 <= 15. At the time of the first sampling event (first (@posedge CLOCK), the value of gP2 is 3. This implies that state condState of coverage_group instance cov1 is not hit in the sampling of sampled variable gVar. This is because the conditional of that bin evaluates to false. In contrast, the bin is hit in the second sampling because at the time of the second sampling event (second (@posedge CLOCK), the value of gP2 is 5.

Functional Coverage 7-74

Expressions within Coverage Group Definitions


Expressions within coverage_group definitions are used for: Specifying a coverage point to be sampled. The result of the expression is sampled when the coverage group is sampled. Defining a value in the range (of values) that defines a state, m_state, bad_state, trans, m_trans, and bad_trans of a sample. These expressions are evaluated at the time the coverage_group is instantiated. Defining a state, ignored, or bad_state bin of a cross (see Valid Expressions for Defining Cross Coverage Bins on page 7-62 for specific restrictions related to such expressions). These expressions are evaluated at the time that the coverage_group is instantiated. Conditional of a user-defined bin in a sample or cross. These expressions are evaluated every time that the coverage_group is sampled. Values of coverage_group, sample, or cross attributes. These expressions are evaluated at the time that the coverage_group is instantiated.

Coverage group expressions are a subset of the general Vera expressions. Expressions must evaluate to an integer, bit vector or enum value. The expressions must have no side effects. They cannot include the ++ or -- operators. The only functions allowed are, get_cycle() and get_time(). The query() method of a coverage_group is only allowed inside of expressions that are used for bin conditionals. The query() and inst_query() methods of a coverage group are only allowed inside of expressions that are used to set values of coverage_group, sample or cross attributes.

Functional Coverage 7-75

The following coverage_group attributes cannot be initialized using the query() or inst_query() function calls: bin_activation_mode cumulative cov_comment overlap_state overlap_trans

These attributes affect the way in which a coverage_group instance is initialized, and therefore their value must be determined before Vera instantiates the coverage_group. The Vera compiler issues an error if you try to initialize the above attribute with the query() or inst_query() function. Interface signals and port variables declared via the bind construct are allowed. Expressions within a coverage_group can reference any variable or signal that is visible in the scope the coverage_group is being defined in, including arguments passed to the coverage_group. For example, an embedded coverage_group can include expressions that refer to the data members of the class (see page 7-4 for the definition of an embedded coverage_group).

Functional Coverage 7-76

Cumulative and Instance-based Coverage


Coverage statistics can be gathered both cumulatively and on a per-instance basis.

Cumulative Coverage
Cumulative implies that coverage statistics (that is, bin hit counts and coverage numbers) are computed for the coverage_group definition. In this case all instances of the coverage_group contribute to a single set of statistics maintained for the coverage_group definition. By default, Vera computes cumulative coverage information. An example of when this kind of coverage is useful is when covering a packet class. Cumulative coverage will provide information for all the packet instances of the class. Note: In cumulative mode, only cumulative information can be queried for. Furthermore, the coverage reports only report on cumulative data for the coverage group definitions, and not instances.

Instance-based Coverage
Instance-based coverage statistics involve computing coverage statistics for every instance of a coverage_group as well as the coverage_group definition as a whole. Vera computes per-instance coverage statistics when you set the cumulative attribute of the coverage_group to 0.

Functional Coverage 7-77

Measuring Coverage
Vera computes a coverage number (or percentage) for the testbench run as whole. Here, the coverage number is referred to as coverage. The coverage for the testbench is the weighted average of the coverages of every coverage_group in the testbench. When per-instance data is available, Vera also computes an instance coverage for the testbench. That number is the weighted average of the coverages of every coverage_group instance. The cov_weight attribute of a coverage_group determines the contribution of that group to the testbench coverage. The section Coverage Attributes on page 7-80 describes coverage_group attributes and mechanisms for setting them. The coverage for each coverage_group is the weighted sum of that groups sample and cross coverage numbers. The cov_weight attribute of a sample determines the contribution of that sample to the coverage of the enclosing coverage group. Similarly, the cov_weight attribute of a cross determines the contribution of that cross to the coverage of the enclosing coverage group. Both attributes have a default value of 1. The Coverage Attributes section describes sample and cross attributes and mechanisms for setting them. Vera computes the coverage number for a sample as the number of bins with the at_least number of hits divided by the total number of possible bins for the sample (multiplied by 100). When the sample is auto-binned (that is, there are no user-defined state or transition bins), the total number of possible bins for the sample is the minimum of the auto_bin_max attribute for that sample and the number of possible values for the coverage point.

Functional Coverage 7-78

Vera computes the coverage number of a cross as the number of bins (of that cross) with the at_least number of hits divided by the total number of bins for that cross (multiplied by 100). By default, the number of possible bins for a cross is the sum of the user-defined bins and the number of possible automatically generated bins for that cross. The number of possible automatically generated bins is the product of the number of possible bins for each of the samples being crossed. Reporting and Querying Coverage Numbers Testbench coverage is reported in the Vera Coverage HTML and text reports. See Unified Coverage Reporting on page 7-86 The reports also include detailed information for each coverage group as well as the samples and crosses of each group. You can also query for the testbench coverage during the Vera run. This allows you to react to the coverage statistics dynamically (for example, stop the Vera run when the testbench achieves a particular coverage). The following system function returns the cumulative coverage (an integer between 0 and 100) for the testbench:
function integer get_coverage();

The following system function returns the instance-based coverage (an integer between -1 and 100) for the testbench:
function integer get_inst_coverage();

Functional Coverage 7-79

Note: The get_inst_coverage() system function returns -1 when there is no instance-based coverage information (that is, the cumulative attribute of the coverage_group has not been set to 0). The section Coverage Feedback: query() on page 7-106 details how to query for the coverage of individual sample and crosses of each coverage_group.

Coverage Attributes
This section lists the attributes that are used as part of the coverage group specification. You can set attributes in the coverage_group, sample, or cross constructs. You can set an attributes value in the coverage groups definition (that is, inside a coverage_group, sample, or cross construct). Syntax
attribute_name = value_expression;

Where attribute_name is the name of the attribute, and value_expression is an OpenVera expression (see Expressions within Coverage Group Definitions on page 7-75 for allowed expressions inside of coverage_group definitions.) When an attribute in a coverage_groups definition is set, the value_expression is evaluated at the time the coverage_group is instantiated. coverage_group attributes can be used for two purposes.

Functional Coverage 7-80

They can be used to control the behavior of a coverage group, as well instances of a coverage group. For example, the coverage_goal attribute defines the coverage goal percentage for the coverage group. They provide a shorthand for setting the corresponding attribute for all samples and crosses of the coverage group that do not explicitly set that attribute.

In Example 7-39, the at_least attribute of embedded coverage group PacketCov is set to 2. Sample m_packetSize of that coverage group sets at_least to 5. Therefore, the sample m_packetSize at_least attribute is set to 5, whereas for sample m_packetId and cross MyCross, at_least is set at 2.

Example 7-39
class Packet { bit [7:0] m_packetSize; bit [7:0] m_packetId; coverage_group PacketCov { at_least = 2; sample m_packetSize { at_least = 5; } sample m_packetId; cross MyCross (m_packetSize, m_packetId); sample_event = @(posedge CLOCK); }

Note: Vera does not force a particular order in the definition of coverage_group-level attributes and the sample and cross definitions. Similarly, Vera does not force any particular order in the definition of sample (or cross) level attributes and the definition of the sample (or cross) bins.

Functional Coverage 7-81

Coverage Group Attributes


at_least: The at_least attribute specifies the minimum number of times a bin should be hit for it to be considered covered. The default value is 1. The at_least attribute can be set at the coverage_group, sample, or cross levels. When it is applied at the sample (or cross) level, it applies to all bins of the sample (or cross). When it is set at the coverage_group level it is applied to all bins of all samples and crosses that do not explicitly set the attribute. auto_bin_max: The auto_bin_max attribute specifies the maximum number of automatically created bins for samples. This attribute has a default value of 64. The auto_bin_max attribute can be set at the coverage_group or sample level. When it is set at the coverage_group level, it applies to all samples in the coverage group that do not explicitly set the attribute. bin_activation: The bin_activation attribute defines the default active/inactive state for user-defined bins of a coverage construct. Please refer to the Activation/Deactivation: User Defined Bins on page 7-100 for more details about this attribute. The value of the expression will be evaluated when the coverage group containing the expression is first instantiated. - If the expression evaluates to 0 (OFF), the Vera coverage engine assumes that all bins for the construct (coverage_group, sample, cross) containing the attribute will be inactive for the current instance and all subsequent instantiations of the coverage group.

Functional Coverage 7-82

- If the expression evaluates to a non-zero value (ON), the Vera coverage engine assumes that all bins for the construct (coverage_group, sample, cross) containing the attribute will be active for the current instance and all subsequent instantiations of the coverage group. collect: The collect attribute turns data collection on or off.The attribute has a default value of ON (or 1). The collect attribute can be set at the coverage_group, sample, or cross levels. When it is set at the coverage_group level, it applies to all samples in the coverage group that do not explicitly set the attribute. cov_comment: This attribute is used to specify user-defined comments (character string literals) in the coverage_group, sample, and cross constructs. The comment can be used as a mnemonic to assist in interpreting coverage results, or help in organizing coverage results in custom ways. Syntax
cov_comment = string_literal;

string_literal
is character string enclosed in double quotes. An OpenVera string variable cannot be used for initializing this attribute. cov_weight: When specified for a coverage_group, the attribute affects how the coverage_group contributes to the overall testbench coverage number. When specified for a sample or cross, this attribute affects how the sample or cross contributes to the enclosing coverage_groups coverage number. The attribute has a default value of 1. Setting this attribute at the coverage_group level does not affect the value of the cov_weight attribute for any of the sample or crosses of the coverage_group.

Functional Coverage 7-83

coverage_goal: When specified for a coverage_group, the attribute designates the desired coverage percentage for the group. The default value is 100 (percent). When specified at the sample or cross level, the attribute specifies the desired coverage percentage for the sample or cross. Again, the default is value 100. Setting coverage_goal at the coverage_group level does not affect the value of the coverage_goal attribute for the sample and crosses of the coverage_group (that is, the attribute retains its default value for the sample and crosses where coverage_goal is not explicitly set). cumulative: The cumulative attribute specifies whether to accumulate coverage data cumulatively across all instances of the coverage group, or on a per-instance basis. The attribute has a default value of ON (or 1). The cumulative attribute is set at the coverage_group level only. overlap_state: The overlap_state attribute specifies whether Vera should check for states with overlapping values. When set to ON (or 1), Vera prints a warning if any two states of a sample have overlapping values. The attribute has a default value of OFF (or 0). The overlap_state attribute can be set at the coverage_group or sample level. When it is set at the coverage_group level, it applies to all samples in the coverage group that do not explicitly set the attribute. overlap_trans: The overlap_trans attribute specifies whether Vera should check for trans constructs that define overlapping transitions. When set to ON (or 1), Vera prints a warning if any two trans constructs of a sample define overlapping transitions. The attribute has a default value of OFF (or 0). The overlap_trans attribute can be set at the coverage_group or sample level. When it is set at the coverage_group level, it applies to all samples in the coverage group that do not explicitly set the attribute.

Functional Coverage 7-84

The following table summarizes coverage attributes, their types and default values. It also indicates whether an attribute can be set at the coverage_group, sample, or cross level

Table 7-7 Coverage Attributes and Related Constructs


Attribute Name Type Default Value
1 64 ON 1 100 ON OFF OFF 1

Defined in coverage_group
Yes Yes Yes Yes Yes Yes Yes Yes Yes

Defined in sample
Yes Yes Yes Yes Yes No Yes Yes Yes

Defined in cross
Yes No Yes Yes Yes No No No Yes

at_least auto_bin_max collect cov_weight coverage_goal cumulative overlap_state overlap_trans bin_activation

integer (>=1) integer boolean integer (>=0) integer (0-100) boolean boolean boolean integer

Coverage Group Instances with Different Attribute Values Each instance of a coverage_group can set a different value to a particular attribute. For example, the first instance of a coverage_group can set the at_least attribute to 5, while the second instance of the same coverage_group sets the at_least attribute to 3. Vera enforces that all instances of a coverage_group have the same setting for the cumulative attribute. The first instance of the coverage_group determines the value of the attribute even if other instances have a different setting. When different instances of a coverage_group have different values for the at_least, or coverage_goal attributes, Vera uses the largest value of each attribute for computing cumulative coverage statistics (that is, coverage numbers for the coverage group). When different

Functional Coverage 7-85

instances of a coverage_group have different values for the cov_weight attribute, Vera uses the smallest value of that attribute for computing cumulative coverage statistics (that is, coverage numbers for the coverage group).

Unified Coverage Reporting


The db based coverage reporting has been replaced by the Unified Report Generator (URG). The URG generates combined reports for all types of coverage information. The reports may be viewed through through an overall summary "dashboard" for the entire design/ testbench. The format of the text report generated by the URG is enhanced and different from the text report that used to be generated by the vera -cov_report command line options. Any scripts that use these old command line options now need to be modified to use the URG options. The functional coverage database files and their location have been changed. The default directory is simv.vdb. The reporting tool shipped with Vera version 2005.12 cannot read coverage databases generated using previous versions of Vera. Similarly, the reporting tool shipped with pre-Vera 2005.12 versions cannot read coverage databases generated using Vera 2005.12.

Coverage Reporting Flow


To generate coverage reports using URG: 1. Create the coverage database (for example, using Vera standalone):

Functional Coverage 7-86

% vera_cs test.vro

This runs a simulation and creates the directory simv.vdb 2. Create the coverage report from the database:
% urg -dir simv.vdb //html % urg -dir simv.vdb -show text //text

This creates the urgReport directory. 3. In order to view the results, invoke a browser (for example, invoke Netscape):
% netscape urgReport/dashboard.html % more urgReport/dashboard.txt

Please refer to the Unified Report generator for details

Coverage Data and Post-processing Tools


Unified Coverage Directory and Database Control
In Vera 2005.12, all the testbench functional coverage data is stored inside a coverage directory named simv.vdb. This is different from previous versions of Vera, where the coverage database files were stored by default in the current working directory or the path specified by coverage_database_filename. For your reference a logical test name is associated with the coverage data that is generated by a simulation. A default test name will be assigned by Vera. You can override this name by using the "coverage_set_database_test_name" task.
task coverage_set_database_test_name (file_name);

Vera avoids overwriting existing database test names by generating unique non-clashing test names for consecutive tests.
Functional Coverage 7-87

For example, if the coverage data is to be saved to a test name called "pci_test", and a database with that test name already exists in the coverage directory "simv.vdb", then Vera automatically generates the new name "pci_test_gen1" for the next simulation run. The following table explains the unique name generation scheme details
Test Name Database

pci_test pci_test_gen_1 pci_test_gen_2 pci_test_gen_n

Database for the first testbench run. Database for the second testbench run. Database for the 3rd testbench run. Database for the nth testbench run.

You can disable this method of ensuring database backup and force Vera to always overwrite an existing coverage database. To do this, use the following system task::
task coverage_backup_database_file (flag ); The value of flag can be: OFF for disabling database backup. ON for enabling database backup.

In order to not save the coverage data to a database file (for example, if there is a verification error), use the following system task:
task coverage_save_database (flag ); The value of flag can be: OFF for disabling database backup. ON for enabling database backup.

Functional Coverage 7-88

Loading Coverage Data


Both cumulative coverage data and instance-specific coverage data can be loaded. The loading of coverage data from a previous Vera run implies that the bin hits from the previous Vera run to this run are to be added. Loading Cumulative Coverage Data The cumulative coverage data can be loaded either for all coverage groups, or for a specific coverage group. To load the cumulative coverage data for all coverage groups, use the following syntax:
coverage_load_cumulative_data("test_name"[, "dir_name"]);

In this task, "dir_name" is optional. If you do not specify a "dir_name", by default, simv.vdb is taken as the directory containing the database. The above task directs Vera to find the cumulative coverage data for all coverage groups found in the specified database file and to load this data if a coverage group with the appropriate name and definition exists in this Vera run. To load the cumulative coverage data for just a single coverage group, use the following syntax:
coverage_load_cumulative_cg_data("test_name", "covergroup_name"[, "dir_name"]);

In this task, "dir_name" is optional. If you do not specify a "dir_name", by default, simv.vdb is taken as the directory containing the database.

Functional Coverage 7-89

In the Example 7-40 below, there is a Vera class MyClass with an embedded coverage object covType. Vera finds the cumulative coverage data for the coverage group MyClass:covType in the database file Run1.db and loads it into the covType embedded coverage group in MyClass.

Example 7-40
MyClass{ integer m_e; coverage_group covType{ sample_event = wait_var(m_e); sample m_e; } } ... ... coverage_load("Run1.db", "MyClass::covType");

Loading Instance Coverage Data The coverage data can be loaded for a specific coverage instance. To load the coverage data for a standalone coverage instance, use the following syntax:
coverage_instance.load("test_name"[, "dir_name"]);

In this task, "dir_name" is optional. If you do not specify a "dir_name", by default, simv.vdb is taken as the directory containing the database. To load the coverage data for an embedded coverage instance, use the following syntax:
class_object.cov_group_name.load("test_name"[, "dir_name"]);

In this task, "dir_name" is optional. If you do not specify a "dir_name", by default, simv.vdb is taken as the directory containing the database.

Functional Coverage 7-90

The commands above direct Vera to find the coverage data for the specified instance name in the database, and load it into the coverage instance. In Example 7-41, there is a Vera class MyClass with an embedded coverage object covType. Two objects obj1 and obj2 are instantiated, each with the embedded coverage group covType. Vera will find the coverage information for the coverage instance obj1:covType from the database file Run1.db, and load this coverage data into the newly instantiated obj1 object. Note that the object obj2 will not be affected as part of this load operation.

Example 7-41
MyClass { integer m_e; coverage_group covType { sample_event = wait_var(m_e); sample m_e; } } ... ... MyClass obj1 = new; obj1.load("Run1.db"); MyClass obj2 = new;

Instance Names
Auto-naming Coverage objects are named so that they can be identified in the Vera coverage reports. By default, the name automatically generated is based on the variable name of the Vera coverage object. In Example 7-42, the name of the coverage instance will be cov1. The full name is covType:cov1.

Functional Coverage 7-91

Example 7-42
coverage_group covType { sample_event = @(posedge CLOCK); sample gVar; } ... covType cov1 = new();

In the case of an array of coverage objects, the names generated for the coverage instances include the array index. In Example 7-43, the coverage instances will be named covInst[0] and covInst[1].

Example 7-43
coverage_group covType(sample integer thisVar) { sample_event = @(posedge CLOCK); sample thisVar; } ... covType covInst[2]; covInst[0] = new(localVar1); covInst[1] = new(localVar2);

User-Specified Names Coverage instances are created dynamically during the simulation run. In some testbenches, a large number of coverage instances may be created. To have greater control, explicitly name the coverage objects to have user-specified names. The syntax for standalone coverage groups is:
coverage_instance.set_name("user_specified_name");

The syntax for an embedded coverage_group is:


class_instance.coverage_group_name.set_name("user_ specified_name");

Functional Coverage 7-92

Predefined Coverage Group Tasks and Functions


Vera provides a set of predefined member functions and tasks for coverage groups. These are referred to as coverage group methods. These predefined methods can be invoked on an instance of a coverage group. They follow the same syntax as invoking class functions and tasks on an object. Although predefined methods are invoked on a coverage group instance, some are related to the cumulative coverage information that Vera maintains for the coverage group as a whole (cumulative coverage group information). For example, the query() function returns coverage information related to the coverage group as a whole (cumulative information). On the other hand, the inst_query() function returns coverage information for the coverage group instance on which it is invoked. If the cumulative attribute of a coverage group is set to OFF, functions that return instance-based information return a -1. The prefix inst_ indicates that the predefined coverage group method is related to instance-based coverage information. (see You Cumulative and Instance-based Coverage on page 7-77 for a description of cumulative and instance-based coverage information. Predefined Functions for the coverage_group Construct Predefined functions can be invoked on an instance of a coverage group and have the following syntax:
function return_type coverage_group_instance_name.function_name ([arguments]);

Functional Coverage 7-93

coverage_group_instance_name
For stand-alone coverage groups, coverage_group_instance_name is simply the name the coverage group instance. For class embedded coverage groups, coverage_group_instance_name has the following form:
object_name.coverage_group_name

where object_name is the name of the class instance, and coverage_group_name is the name of the coverage_group construct embedded in the class.

function_name
The following table summarizes the predefined coverage group functions and provides a brief description.

Table 7-8 Predefined Coverage Group Functions


Function Name
get_at_least() get_auto_bin_max()

Requires
Args
No No

Description
Returns the value of the cumulative at_least attribute for the coverage_group definition. Returns the value of the cumulative auto_bin_max attribute for the coverage group definition. Returns the value of the cumulative cov_weight attribute for the coverage group definition. Returns the value of the cumulative coverage_goal attribute for the coverage group definition. Returns the value of the at_least attribute for the coverage group instance. Returns the value of the auto_bin_max attribute for the coverage group instance. Returns the value of the collect attribute for the coverage group instance. Returns the value of the cov_weight attribute for the coverage group instance.

get_cov_weight() get_coverage_goal()

No No

inst_get_at_least() inst_get_auto_bin_max() inst_get_collect() inst_get_cov_weight()()

No No No No

Functional Coverage 7-94

Table 7-8 Predefined Coverage Group Functions


Function Name
inst_get_coverage_goal inst_query() inst_set_bin_activation() set_bin_activation() query() query_str()

Requires
Args
No Yes Yes Yes Yes Yes

Description
Returns the value of the coverage_goal attribute for the coverage group instance. Queries for coverage information related to the coverage group instance. Returns the number of bins affected by the function. Returns the number of bins affected by the function. Queries for coverage information related to the coverage group as a whole (cumulative). Queries for the name of the current sample or cross bin in a query(FIRST)/query(NEXT) or inst_query(FIRST)/inst_query(NEXT) sequence.

arguments
Some of the predefined coverage group functions accept arguments. The second column of Table 7-8 indicates whether a function requires an argument.

return_type
All predefined coverage group functions have an integer return type except for query_str(), which has a string return type. Predefined Tasks for The coverage_group Construct Predefined tasks can be invoked on an instance of a coverage group and have the following syntax
task coverage_group_instance_name.task_name (argument);

Functional Coverage 7-95

coverage_group_instance_name
For stand-alone coverage groups, coverage_group_instance_name is simply the name the coverage group instance. For class embedded coverage groups, coverage_group_instance_name has the following form:
object_name.coverage_group_name

where object_name is the name of the class instance, and coverage_group_name is the name of the coverage_group construct embedded in the class.

task_name
The following table summarizes the predefined coverage group tasks and provides a brief description.

Table 7-9 Predefined Coverage Group Tasks


Task Name
set_at_least()

Argument type
integer

Description
Sets the cumulative at_least attribute (which is used for computing cumulative coverage statistics). Sets the cumulative auto_bin_max attribute (which is used for controlling cumulative coverage information). Sets the cumulative cov_weight attribute (which is used for computing cumulative coverage statistics). Sets the cumulative coverage_goal attribute (which is used for computing cumulative coverage statistics). Sets the at_least attribute for the coverage group instance. Sets the auto_bin_max attribute for the coverage group instance. Sets the collect attribute for the coverage group instance (turning off coverage data collection for that instance).

set_auto_bin_max()

integer

set_cov_weight()

integer

set_coverage_goal()

integer

inst_set_at_least() inst_set_auto_bin_max() inst_set_collect()

integer integer integer

Functional Coverage 7-96

Table 7-9 Predefined Coverage Group Tasks


Task Name
inst_set_cov_weight() inst_set_coverage_goal() load() set_name()

Argument type
integer integer string string

Description
Sets the cov_weight attribute for the coverage group instance. Sets the coverage_goal attribute for the coverage group instance. Loads data for the coverage group instance from the Vera functional coverage database. Sets the name of the coverage group instance.

argument: All predefined coverage group tasks require an argument. The second column of Table 7-9 indicates the type of the argument for each task. Predefined Coverage Group Tasks and Functions for Sample and Cross Constructs Vera also provides predefined tasks and functions for the samples and crosses of a coverage group. You can invoke these methods on a sample or cross of a coverage group instance. When invoked on a sample or cross, predefined coverage group functions have the following syntax:
function integer coverage_instance_name.member_name.method_name ([arguments]);

When invoked on a sample or cross, predefined coverage group tasks have the following syntax:
task coverage_instance_name.member_name.method_name (argument);

Functional Coverage 7-97

coverage_instance_name
For stand-alone coverage groups, coverage_instance_name is simply the name the coverage group instance. For class embedded coverage groups, coverage_instance_name has the following form:
object_name.coverage_group_name

where object_name is the name of the class instance, and coverage_group_name is the name of the coverage_group construct embedded in the class.

member_name
Name of the coverage group sample or cross construct

argument
All predefined coverage group tasks require an argument. The second column of Table 7-9 indicates the type of the argument for each task.

method_name
Name of a predefined task or function that can be invoked on a sample or cross of the coverage_group construct. Table 7-10 lists the methods that can be invoked on a sample or cross .

Table 7-10 Predefined Coverage Group Methods for Samples or Crosses


Method Name
get_at_least() get_cov_weight() get_coverage_goal()

Description
Returns the value of the cumulative at_least attribute for a sample or cross. Returns the value of the cumulative cov_weight attribute for a sample or cross. Returns the value of the cumulative coverage_goal attribute for a sample or cross.

Functional Coverage 7-98

Table 7-10 Predefined Coverage Group Methods for Samples or Crosses


Method Name
inst_get_at_least() inst_get_cov_weight() inst_get_coverage_goal() inst_query() query() query_str()

Description
Returns the value of the at_least attribute for a sample or cross of a coverage group instance. Returns the value of the cov_weight attribute for a sample or cross of a coverage group instance. Returns the value of the coverage_goal attribute for a sample or cross of a coverage group instance. Queries for coverage information related to a sample or cross of a coverage group instance. Queries for cumulative coverage information related to a sample or cross of a coverage group. Queries for the name of the current sample or cross bin in a query(FIRST)/query(NEXT) or inst_query(FIRST)/ inst_query(NEXT) sequence. Sets the cumulative at_least attribute (which is used for computing cumulative coverage statistics). Sets the cumulative cov_weight attribute (which is used for computing cumulative coverage statistics). Sets the cumulative coverage_goal attribute (which is used for computing cumulative coverage statistics). Sets the at_least attribute for the coverage group instance. Activates/deactivates a user-defined state/transition bin for a coverage_group instance. Sets the cov_weight attribute for the coverage group instance. Sets the coverage_goal attribute for the coverage group instance. Deactivates/activates a user-defined state/transition bin for a coverage_group definition, as well as the instance on which the function was invoked.

set_at_least() set_cov_weight() set_coverage_goal() inst_set_at_least() inst_set_bin_activation() inst_set_cov_weight() inst_set_coverage_goal() set_bin_activation()

Functional Coverage 7-99

Table 7-11 lists the methods that can only be invoked on a sample of the coverage_group construct.

Table 7-11 Predefined Coverage Group Methods for Samples Only


Method Name
get_auto_bin_max() inst_get_auto_bin_max() set_auto_bin_max()

Description
Returns the value of the cumulative auto_bin_max attribute for a sample. Returns the value of the auto_bin_max attribute for a sample of coverage group instance. Sets the cumulative auto_bin_max attribute (which is used for controlling cumulative coverage information) on a sample. Sets the auto_bin_max attribute for a sample of a coverage group instance.

inst_set_auto_bin_max()

The methods listed in the above two tables are a subset of predefined methods for the coverage_group construct.

Activation/Deactivation: User Defined Bins


The Vera functional coverage engine assumes that all user-defined bins (state and transition) in a coverage_group definition are of interest to the user, therefore the coverage data is computed and reported for all user-defined bins. However, there are scenarios where a user may be interested in only a subset of the user defined bins. One scenario is that a verification engineer develops a functional coverage model for an interface based on the general specification of the interface. A client of the interface would like to be able to use this functional coverage model (perhaps embedded in a set of classes). However the client knows that certain aspects of the interface will not be used in their usage of the interface (based on the particular environment that the interface is being used in). Hence, some of the user-defined state/transition bins of the general
Functional Coverage 7-100

functional coverage model are not applicable and must be inactive. If the bins are left active, the client would see overly pessimistic results. An active user-defined bin is one that is of interest to the user, and contributes to the overall coverage of the testbench. An inactive user-defined bin is one that is not of interest to the user, and should not be considered for coverage reporting and coverage calculation purposes. By default, all user defined bins are considered active. Since Vera 6.1, functional coverage has provided an attribute based mechanism for setting all user-defined bins in a coverage construct as inactive. Further, Vera 6.1 and up also provides two built-in functions that select a subset of user defined bins for a coverage construct to be active or inactive. The attribute is called bin_activation, and the built-in functions are set_bin_activation() and inst_set_bin_activation(). The bin_activation attribute defines the default active/inactive state for user defined bins of a coverage construct. As with other coverage attributes, this attribute can be set for a coverage_group, sample or cross construct. The syntax for setting this attribute is:
bin_activation = value_expression;

value_expression
Is an OpenVera expression. The value of the expression will be evaluated when the coverage group containing the expression is first instantiated.

Functional Coverage 7-101

If the expression evaluates to 0 (OFF), the Vera coverage engine assumes that all bins for the construct (coverage_group, sample, cross) containing the attribute will be inactive for the current instance and all subsequent instantiations of the coverage group. If the expression evaluates to a non-zero value (ON), the Vera coverage engine assumes that all bins for the construct (for example, coverage_group, sample, cross) containing the attribute will be active for the current instance and all subsequent instantiations of the coverage group. The default active/inactive state of user defined bins can be overridden using the functions, set_bin_activation() and inst_set_bin_activation(). The functions follow the same invocation syntax as other pre-defined functions (for example, query() and inst_query()). The integer value returned by these two functions is the number of bins acted upon by the function. set_bin_activation() This function deactivates/activates a user-defined state/transition bin for a coverage_group definition, as well as the instance on which the function was invoked. Syntax
integer function set_bin_activation(integer command, [integer bin_type[, string bin_name_pattern]]);

command Is either OFF (for deactivating a bin) or ON (for reactivating a bin).

Functional Coverage 7-102

bin_type
Is an optional argument, which can be any of the valid bin types: STATE, BAD_STATE, TRANS, BAD_TRANS. The bin_type argument controls the set of bins on which the command is to be applied. Multiple bin types can be specified using the or operator (|). If the bin_type is not specified, the command is applied to all bins. If specified, the bin_type argument must follow the command argument.

bin_pattern
Is an optional argument that is used to further control the set of bins upon which the command is applied. It can be any Perl regular expression. Only those user defined bins of type bin_type, whose names match the bin_pattern are affected by the command. If no bin_pattern is specified, then the command is applied to all bins of the type bin_type. If the bin_pattern is specified, then it must follow the command and bin_type arguments. When a user-defined state/transition bin for a coverage_group definition is deactivated, the user-defined state/transition bin is taken out of consideration for cumulative coverage computation and instance coverage computation for the instance upon which the function was invoked. Instance and cumulative hit counts are not updated, and the bins are not considered when computing cumulative coverage numbers and instance coverage numbers for the affected instance. Note that if bins are deactivated using this command, subsequent instantiations of the coverage group will also have the bins deactivated (irrespective of the value of the bin_activation attribute for the new instance). If a particular instance of the coverage_group needs to be activated or deactivated, a separate function inst_set_bin_activation() can be used.
Functional Coverage 7-103

inst_set_bin_activation() This function activates/deactivates a user-defined state/transition bin for a coverage_group instance.
integer function inst_set_bin_activation(integer command, [integer bin_type[, string bin_pattern]]);

command
is either OFF (for deactivating a bin) or ON (for reactivating a bin).

bin_type
Is an optional argument, which can be any of the valid bin types: STATE, BAD_STATE, TRANS, BAD_TRANS. The bin_type argument controls the set of bins upon which the command is to be applied. Multiple bin types can be specified using the or operator (|). If the bin_type is not specified, the command will be applied to all bins. If specified, the bin_type argument must follow the command argument.

bin_pattern
Is an optional argument that is used to further control the set of bins upon which the command is applied. It can be any Perl regular expression. Only those user defined bins of type bin_type, whose names match the bin_pattern are affected by the command. If no bin_pattern is specified, then the command is applied to all bins of the type bin_type. If the bin_pattern is specified, then it must follow the command and bin_type arguments. When a user-defined state/transition bin for a coverage_group instance is deactivated, the user-defined state/transition bin is taken out of consideration for instance-based coverage computation. The instance based hits counts and the cumulative hit counts for the inactive bin are not updated. The inactive bin is not considered when

Functional Coverage 7-104

computing instance-based coverage numbers, and the inactive bin does not show up in the instance-based coverage report for the coverage_group instance. Example 7-44 illustrates the use of the bin_activation attribute and the set_bin_activation() function.

Example 7-44
#define READ 4'b0000 #define WRITE 4'b0001 class Driver { bit [31:0] addr; bit [3:0] mode; coverage_group Cov { sample addr; sample mode { state s_read(READ); state s_write(WRITE); } cross add_mode(addr, mode) { state s_read(addr == READ); state s_write(addr == WRITE); } sample_event = @(posedge CLOCK); bin_activation = 1; //all bins active by default } } program test{ Driver ifc = new; integer num_bins; // deactivate any user-defined sample or cross // STATE bin that starts with s_wr num_bins = ifc.Cov.set_bin_activation(OFF, STATE, "s_wr.*"); // deactivate any user-defined bin in // cross add_mode that starts with s_re num_bins = ifc.Cov.add_mode.set_bin_activation (OFF,"s_re.*"); }

Functional Coverage 7-105

Coverage Feedback: query()


One of the predefined coverage group functions that is mentioned in the previous section is the query() function. This function allows monitoring of the functional coverage statistics during the Vera run, as well as enabling dynamic reactions to the functional coverage results. The query() function can be invoked on a coverage group instance, or a sample or cross of a coverage group instance. You can use the query() function to: obtain the current coverage number (percentage) of a coverage group or of a sample or cross of a coverage group query whether the coverage goal of a group (or a sample or cross of a coverage group) is met count the number of hits for a particular sample or cross bin count the number of bins (of a particular type--that is, state or transition) of a sample or cross iterate through the bins of a coverage group, or a sample or cross of a coverage group

Note: The query() function is used for retrieving cumulative information related to the coverage group as a whole. It is not used for retrieving coverage information for a particular instance of a coverage group. If you have set the cumulative attribute of a coverage_group to OFF, you can retrieve both cumulative as well as instance-based coverage information. In that case, you can use the inst_query() function for retrieving instance-specific information and the query() function for retrieving cumulative coverage information. The syntax for the inst_query() function is

Functional Coverage 7-106

exactly the same as the query() function. We will illustrate this point with an example after introducing the syntax of the query() function. The query() functions are in these forms:
function function function function integer integer integer integer query(command); query(command, bin_type); query(command, bin_type,bin_pattern); query(command, bin_type,bin_pattern, operand, hit);

The basic form of query() allows you to specify one of several commands: COVERAGE, NUM_BIN, SUM, FIRST, NEXT, GOAL, and SAMPLE. Each command returns a different value based on the bin_type.

Table 7-12
Command
COVERAGE GOAL NUM_BIN SUM FIRST

Function
Returns the current coverage number (percentage). You do not pass any other arguments when using this command. Returns a 1 if the coverage goal has been met (0 otherwise). You do not pass any other arguments when using this command. Counts the number of bins of type bin_type. Sums the counters for all bins of type bin_type. Returns the count of the first bin of type bin_type (or -1 for failure). It starts an iteration sequence through bins of type bin_type. Returns the count of the next bin of type bin_type in the sequence started with FIRST (or -1 if the sequence is complete). You do not pass any other arguments when using this command. Returns the sampled value of the indicated coverage point (sample construct). This command requires an additional integer argument which is the depth of the sampled value. This command is discussed in the following Temporal Coverage section.

NEXT

SAMPLE

Functional Coverage 7-107

The single-argument form of the command applies to all bins. The additional arguments can be added to narrow the bin selection.

bin_type
The bin_type is any of the valid bin types: - STATE - BAD_STATE - TRANS - BAD_TRANS Multiple bin types can be specified using the or operator (|).

bin_pattern
The bin_pattern variable is matched against the bin names of the specified type. It can be any regular Perl expression. Only those bins whose names contain the bin_pattern are included in the query. For example, if bin_pattern is bus, all bins with bus in their names will be included. If you want to select all bins whose names begin with a specific string, insert a caret (^) before the string (such as ^bus). To select all bins of the specified type regardless of name, use ".*" as the bin_pattern.

operand
The operand must be one of: - GT (greater than) - GE (greater than or equal to) - LT (less than) - LE (less than or equal to) - EQ (equal to)
Functional Coverage 7-108

- NE (not equal to)

hit
Hit specifies the number of counter hits to which the query is compared using the operand. It can be any non-negative integer. Outside of a coverage declaration we need to qualify query() to get the appropriate method. For example, to get the query method for the cp0 coverage object, we would use cp0.query(). Querying Coverage Objects, Samples and Crosses (Examples) The query() method can be invoked on: coverage_group instances (embedded as well as stand-alone) samples of coverage_group instances crosses of coverage_group instances

When the query() method is invoked on a coverage instance, the method operates on all samples and cross constructs within the coverage instance. The coverage numbers and bin counts returned are the aggregation across all samples and constructs.

Example 7-45
class MyClass{ integer m_x, m_y; coverage_group covType{ sample_event = wait_var(m_e); sample m_x; sample m_y { m_state (0:10); m_trans (0:10->0:10); } cross cc1 (m_x, m_y); } } ... MyClass obj1 = new;

Functional Coverage 7-109

...

For Example 7-45, the query: numCrossBins = obj1.covType.query(COVERAGE); returns the coverage number (coverage percentage) for the embedded coverage group covType of class MyClass: numBins = obj1.covType.query(SUM); returns the total hit count of all sample and cross bins in embedded covType coverage group for object obj1. done = obj1.covType.m_x.query(GOAL); returns 1 if the coverage goal associated with the m_x sample in the embedded coverage group has been met. numCrossBins = obj1.covType.cc1.query(NUM_BIN); returns the number of bins created for the cc1 cross in the embedded coverage group covType of object obj1 In the following statement, we compute the sum of the bin counts for state or transition bins with counts greater than 10 each:
numBins = obj1.covType.query(SUM, STATE|TRANS, ".*", GT, 10);

In the following loop, we continue a process until at least 10 bins of sample m_y have 10 or more hits:
while (obj1.covType.m_y.query(NUM_BIN, STATE|TRANS, ".*", GT, 10) < 11) {...}

Functional Coverage 7-110

You can also set up loops that continue processes until the coverage goal is met:
while (!obj1.covType.query(GOAL)){...}

Querying Cumulative and Instance-Based Information The query() function is used for retrieving cumulative information related to the coverage group as a whole. It is not used for retrieving coverage information for a particular instance of a coverage group. If you have set the cumulative attribute of a coverage_group to OFF, you can retrieve both cumulative as well as instance-based coverage information. In that case, you can use the inst_query() function for retrieving instance-specific information and the query() function for retrieving cumulative coverage information. The syntax for the inst_query() function is exactly the same as the query() function. We will illustrate this with the following complete example:

Example 7-46
#include <vera_defines.vrh> class MyClass{ integer m_var; coverage_group MyCov{ sample m_var; sample_event = @(posedge CLOCK); cumulative = OFF; } } program simple{ MyClass obj1 = new(); MyClass obj2 = new(); @(posedge CLOCK); obj1.m_var = 100; obj2.m_var = 200; @(posedge CLOCK); obj1.m_var = 300; @(posedge CLOCK); printf("MyCov.m_var bins: %0d\n", obj1.MyCov.m_var.query(NUM_BIN)); printf("MyCov.m_var bins: %0d\n",

Functional Coverage 7-111

obj2.MyCov.m_var.query(NUM_BIN)); printf("obj1.MyCov.m_var bins: %0d\n", obj1.MyCov.m_var.inst_query(NUM_BIN)); printf("obj2.MyCov.m_var bins: %0d\n", obj2.MyCov.m_var.inst_query(NUM_BIN)); }

The above print statements produce the following output:


MyCov.m_var bins: 3 MyCov.m_var bins: 3 obj1.MyCov.m_var bins: 2 obj2.MyCov.m_var bins: 1

In this example the cumulative attribute of embedded coverage group MyCov is set to OFF. There are two instances of class MyClass and therefore two instances of coverage group MyCov. When the query function is invoked on obj1.MyCov.m_var, Vera returns the number of bins that are created for sample m_var of coverage_group MyCov as a whole. This is the same number that is returned when the query function is invoked on obj2.MyCov.m_var. On the other, hand the inst_query() function calls return the number of bins that are created for the m_var sample of each of the instances of MyCov. This number is different for obj1.MyCov.m_var and obj2.MyCov.m_var. If the cumulative attribute is not set to OFF (left at its default value of ON), the print statements produce the following output:
MyCov.m_var bins: 3 MyCov.m_var bins: 3 obj1.MyCov.m_var bins: -1 obj2.MyCov.m_var bins: -1

Functional Coverage 7-112

When the cumulative attribute is not set to OFF, Vera only maintains cumulative information for the coverage group as whole. In that case Vera does not maintain per instance information. Querying The Name of a Bin It is also possible to query the name of a monitor bin using the predefined query_str() function of the coverage_group construct. This function can be invoked on a coverage group instance as well as the sample or cross of a coverage group instance. Syntax
function string query_str(NAME);

This function returns the monitor bin name in a FIRST/NEXT series (or NOT_FOUND if the series is complete). Temporal Coverage To return past values of a coverage groups coverage point (that is, sample construct of a coverage_group construct) you can use the predefined query() function of the coverage_group. You can only retrieve previous values of a coverage groups coverage point, if the sample construct associated with that coverage point defines transition bins (using the trans construct). Syntax
function data_type query(SAMPLE, integer depth);

data_type
Can be a bit, bit vector, integer, or an enumerated type.

Functional Coverage 7-113

depth
Is an unsigned integer, which specifies the previously sampled value that is returned. If the sample does not define any transition sequences, then depth must be less than 2. If the sample defines transition sequences, then depth must be less than the length of any of the transition sequences. Otherwise, a simulation error occurs. If the command to the query() function is SAMPLE, then the function must be invoked on the sample of the coverage group instance. When the query() function of a coverage group is called with the SAMPLE keyword, the value of the sampled coverage point associated with the depth is returned. If you specify a depth of 0, the last sampled value of the coverage point is returned. This is the value of the coverage point that was sampled by the Vera coverage engine the last time that the sampling event triggered. If you specify a depth of 1, the function returns the sampled value of the coverage point 2 sampling event triggers prior to the call. If you specify a depth that has not yet occurred, an unknown value (x) is returned. This example returns the sampled value of sampled variable gVar of coverage group instance cov1, three sampling event triggers prior to the call:
integer i = c1.query(SAMPLE, 2);

Functional Coverage 7-114

Pre Vera X-2005.12


Compile-Time Option: -covg_compat
A new command line argument, the coverage compatibility option, -covg_compat (similar to -random_compat), has been added to the compile-time options. This option enables Vera to compile the source file in the old (pre-Vera 2005.12) semantics for coverage and disables, all the new coverage features such as: SV style auto binning New semantics for cross bins Accurate cross coverage computation Accurate hole analysis for cover points and crosses Default coverage goal changed to 100 percent

Syntax:
vera cmp covg_compat [-other_compile_options] file.vr

All .vro files given as input at runtime must have been compiled with the -covg_compat option. If not, the runtime loader issues an error message. The database generated using the -covg_compat option cannot be merged with a database generated without using this option and vice versa.

Functional Coverage 7-115

Auto-Bin Creation
When you let Vera automatically create state bins for a coverage point you do not need to specify states for that coverage point. In that case you use the following shorthand syntax (see Defining Sampled Coverage Points on page 7-21 for full definition) for defining the coverage point:
sample coverage_point [, coverage_point,...];

Note that you can refer to multiple coverage points in a single sample statement. In Example 7-9, Vera automatically creates state bins for coverage points m_x and m_y.

Example 7-47
class MyClass{ bit [0:7] m_x, m_y; coverage_group cov1 { sample_event = @(posedge CLOCK); sample m_x, m_y; } }

By default, Vera creates automatic state bins for the first 64 distinct sampled values of a coverage point. Each bin will have a name of the form:
s_value

In the case of coverage points of enumerated types, the automatically created bin uses the enumerated value name and not its integer value. The number of distinct sampled values that are binned can be controlled using the auto_bin_max attribute. This attribute can be specified inside of a sample construct (and applies to that coverage

Functional Coverage 7-116

point only) or can be specified at the coverage_group level for all coverage points of the group (see the Coverage Group Attributes section in the OpenVera LRM:Testbench manual for details). Note: For enumerated types, auto_bin_max has no effect.
sample a { auto_bin_max = 7; }

or
// affects all samples coverage_group cg { auto_bin_max = 20; sample a, b; sample e (a + b) { } }

or
... sample a, b { auto_bin_max = 7; }// affects both a and b

Vera creates a special state bin named s_OTHERS once the number of distinct sampled values of an auto-binned coverage point exceeds the auto_bin_max value (default of 64). Throughout the simulation, if the sampled value of the coverage point matches one of the first auto_bin_max values, then the hit count for the appropriate automatically generated bin is incremented. Otherwise, the hit count for the s_OTHERS bin is incremented.

Functional Coverage 7-117

Example 7-10 shows a fragment of Vera code that defines a coverage_group with automatically created bins for global sampled variables m_x and m_y. The auto_bin_max attribute has been used to limit the number automatically created state bins to 2. Shown are, the bins created for the sampled variables for the first three @(posedge CLOCK) after the instantiation of the coverage_group.

Example 7-48
coverage_group cov1 { sample_event = @(posedge CLOCK); sample m_x, m_y; auto_bin_max = 2; // max of 2 auto-created bins } ... m_x = 12; m_y = 23; @(posedge CLOCK); m_x = 21; m_y = 23; @(posedge CLOCK); m_x = 13; m_y = 24; @(posedge CLOCK);

The Table 7-1 shows the automatically created bins (and their hit counts) after the first @(posedge CLOCK):

Table 7-13 Automatically generated bins after the first @(posedge CLOCK)
Sampled Variable
m_x m_y

Bin Name
S_12 S_23

Hit Count
1 1

Functional Coverage 7-118

The Table 7-4 shows the automatically created bins (and their hit counts) after the second @(posedge CLOCK):

Table 7-14 Automatically generated bins after the second @(posedge CLOCK)
Sampled Variable
m_x

Bin Name
S_12 S_21

Hit Count
1 1 2

m_y

S_23

TheTable 7-5 shows the automatically created bins (and their hit counts) after third (and final) @(posedge CLOCK):

Table 7-15 Automatically generated bins after the third @(posedge CLOCK)
Sampled Variable
m_x

Bin Name
S_12 S_21 S_OTHERS

Hit Count
1 1 1 2 1

m_y

S_23 S_24

Automatically Generated Bins for Enumerated Types When a coverage point is of an enumerated type, Vera automatically creates state bins for each enumerated value of the coverage point. In this case, the auto_bin_max attribute does not affect the number of automatically created bins. A coverage point which is an expression is considered to be of an enumerated type, if all the operands are of the same enumerated type. Otherwise the type of the coverage point expression depends on the type and width of the sampled expression.

Functional Coverage 7-119

In Example 7-11, coverage_group covType samples the global variable sParam which is of the enumerated type, cellType.

Example 7-49
enum cellType = blue, red, green; extern cellType sParam; coverage_group covType { sample_event = wait_var(sParam); sample sParam; auto_bin_max = 2; // Does not affect the number // auto-bins for sParam }

Vera will automatically create three state bins even though the auto_bin_max attribute has been set to 2.Example 7-11 is shorthand for explicitly typing out the following coverage_group:

Example 7-50
coverage_group covType { sample_event = wait_var(sParam); sample sParam{ state s_blue(blue); // sParam == blue state s_red(red); // sParam == red state s_green(green); // sParam == green } }

Functional Coverage 7-120

Cross Coverage
You can define cross coverage by crossing subsets of the coverage points being sampled by a coverage_group. Crosses of coverage points of a coverage_group can be specified using the cross construct. In its simplest form the cross construct has the following form:
cross cross_name (coverage_point, coverage _point, ...);

In this case Vera automatically creates bins for the cross product of state or transition bins that are hit in each sampled coverage point. The integration of cross coverage into the coverage model specification ensures a tighter and easier to understand semantics. Crosses are specified up front in the coverage_group specification and refer to the coverage points in the same coverage_group. All crosses (cross constructs) and coverage points (sample constructs) are sampled using the same sampling event (sample_event of the coverage_group). In Example 7-22, embedded coverage_group cov1 samples two data members of the embedding class MyClass (data members m_x and m_y), as well as a global variable g_var1. The coverage_group defines a cross named cc1 for crossing sampled variables m_y and g_var1. Note that since we have not defined any state or transitions for the sampled variables, Vera automatically creates state bins for the sampled variables. Cross cc1 will include bins associated with the cross product of the automatically generated bins for the sampled variables m_y and g_var1.

Functional Coverage 7-121

Example 7-51
extern integer g_var1; class MyClass { bit [3:0] m_x; integer m_y; bit m_z; coverage_group cov1 { sample_event = @(posedge CLOCK); sample m_x, m_y, g_var1; cross cc1(m_y, g_var1); } } ... MyClass Obj1 = new; ... Obj1.m_y = 20; g_var1 = 2; @(posedge CLOCK); // First sampling event @(posedge CLOCK); // Second sampling event Obj.m_y++; @(posedge CLOCK); // Third sampling event ...

After the first sampling event Vera creates an automatic state bin s_20 for sampled variable m_y and an automatic state bin s_2 for sampled variable g_var1. Each bin has a hit count of 1. Vera then creates an automatic cross bin (s_20, s_2) for cross cc1. This bin is associated with the cross product of m_y and g_var bins that are hit at this sample point. The bin has a hit count of 1. After the second sampling event Vera increments the hit count for bin s_20 of sampled variable m_y, bin s_2 of sampled variable g_var1, and bin (s_20, s_2) of cross cc1. After the third sampling event Vera creates a new automatic state bin s_21 for sampled variable m_y, and increments the hit count of bin s_2 of sampled variable g_var1. Vera then creates a new bin (s_21,

Functional Coverage 7-122

s_2) for cross cc1 with hit count of 1.In general you can have several crosses in a coverage_group definition. Example 7-52 shows crosses cc1 and cc2 defined inside of a coverage_group.

Example 7-52
class MyClass { bit [3:0] m_x; integer m_y; bit m_z; coverage_group cov1 { sample_event = @(posedge CLOCK); sample m_x, m_y, g_var1; cross cc1(m_y, g_var1); cross cc2(m_x, m_y, g_var1); } }

User-defined Cross Coverage Bins


You can define your cross coverage bins. User-defined (and named) cross coverage bins can be used for: defining illegal cross products defining cross products that should be ignored Combining cross products into a single named bin or equivalence class

You can use Vera expressions for easy and concise specification of cross coverage bins. The syntax for a cross construct that defines cross coverage bins is:
cross cross_name (coverage_point, coverage_point...) { [cross_bin_definitions] [attribute_definitions] }

Functional Coverage 7-123

cross_name
Is the name for the cross. You can use this name to access the cross (query or set information about the cross) in the testbench.

cross_bin_definitions
You can use Vera expressions for defining named cross coverage bins. To define a cross coverage bin that combines several cross products into single named bin or equivalence class use the following syntax:
state state_name (expression) [ if (expression) ];

If the expression for the state evaluates to true, then cross coverage bin state_names hit count is incremented. You can optionally specify a conditional for the cross coverage state. In that case the bin is only hit if both the expression that defines the bin as well as the conditional evaluate to true. To define cross products that should not be considered for coverage calculations, use the ignored keyword. Syntax
ignored state_name (expression) [ if (expression) ];

If the expression for the ignored cross coverage bin evaluates to true, then the enclosing cross is skipped, and none of its bins are updated. To define cross products that are illegal and should not occur, use the bad_state keyword Syntax
bad_state state_name (expression) [ if (expression) ];

Functional Coverage 7-124

If the expression for the bad_state evaluates to true, then Vera issues a verification error.

attribute_definitions
You can use attributes for controlling various aspects of a cross. The Coverage Attributes on page 7-80 section details the attributes that can be specified at the cross level, as well as their default values. You can specify an attributes value as follows:
attribute_name = value_expression;

where attribute_name is the name of the attribute, and value_expression is a Vera expression. See section Expressions within Coverage Group Definitions on page 7-75 for allowed expressions inside of coverage_group and coverage point definitions. Precedence Semantics for User Defined Cross Bins You can have several user-defined cross coverage bins of each kind (that is, state, bad_state, and ignored). The question that arises is how should Vera behave when your cross construct includes user-defined cross coverage bins of each kind. Moreover, what should the precedence semantics be when the expression for more than one of the user-defined cross coverage bins evaluates to true?

Example 7-53
extern i, j, k; coverage_group cov1 { sample_event = @(posedge CLOCK); sample i, j, k; cross cc1 (i,j) { state MyCrossBin(i < 50 ); ignored IgnoredCrossProds(i > 40 && j > 20 && j < 26); bad_state BadCrossProds(i == 45 && j == 24); } }

Functional Coverage 7-125

The following describes Veras precedence semantics when a cross construct includes one or more state, bad_state, and ignored bins. If any of the illegal bins (bad_state) is matched (expression evaluates to true), then Vera issues a verification error. Otherwise, if any of the ignored bins (ignore) is matched, Vera does not update or add any bins and proceeds to the next cross (if any). Otherwise, every one of the user defined (non-illegal, non-ignored) cross coverage bins (state) that match (expression evaluates to true) are updated (that is, their hit count is incremented). Otherwise, Vera creates an automatic cross product bin (if necessary), and updates the hit count of that bin. The bin is associated with the state and/or transition bins that are hit in each coverage point involved in the cross.

We will now analyze Example 7-23 for different values of sampled variables i, j, and k using the precedence semantics described above. If i is 45 and j is 24, then the expressions for all three bins evaluate to true, according to the precedence semantics described above. Vera flags a verification error, and does not proceed to update the hit count for MyCrossBin. Vera does not ignore the cross either, even though the expression for IgnoredCrossProds also evaluates to true. bad_states have the highest precedence. If i is 45 and j is 25, the expressions for both IgnoredCrossProd and MyCrossBin (but not BadCrossProds) evaluate to true. In this case, Vera gives higher precedence to the ignored cross coverage state, and skips cross MyCross. The hit count for MyCrossBin is not updated.
Functional Coverage 7-126

If i is 45 and j is 26, then MyCrossBin is the only user-defined bin whose expression evaluates to true. That bins hit count is incremented. Finally, if i is 50 and j is 27, then none of user-defined bin expressions evaluate to true. In that case Vera automatically creates a cross product bin (s_50, s_27) for cross MyCross. If the bin already exists, then its hit count is incremented. Examples of Embedded Coverage Groups with User-defined Cross Coverage Bins In the following code fragment we show an embedded coverage_group that defines a cross cc1 for sampled variables m_y, m_z, and g_var1.

Example 7-54
class MyClass { ... coverage_group cov1 { sample_event = @(posedge CLOCK); sample m_x, m_y, g_var1; cross cc1(m_y, m_z, g_var1) { bad_state bad1(m_y < 12 && m_z == 0 || m_y > 1024 && g_var1 == 0); ignored ig1(m_y < 128 && m_z == 0); } } }

We have used a Vera expression for defining an illegal (bad_state) cross product named bad1. If the expression evaluates to true at the time that the cross is sampled we issue a verification error. We have also used a Vera expression for defining the set of cross products that should be ignored by coverage. This is accomplished by using the ignore statement in conjunction with a Vera expression that evaluates to true when m_y is less than 128 and m_z is 0. Vera will

Functional Coverage 7-127

not update or create any cross product bins when the ignore state is satisfied. If the illegal and ignored cross states are not satisfied, Vera proceeds to create automatic cross bins. In Example 7-25, an embedded coverage_group defines a cross cc1 for sampled variables m_y, m_z, and g_var1.

Example 7-55
extern integer g_var1; class MyClass { bit [0:4] m_x, m_y; coverage_group cov1 { sample_event = @(posedge CLOCK); sample m_x, m_y, g_var1; cross cc1(m_y, m_z, g_var1) { state s1 (m_y == 0 && m_z == 2); } } }

At each positive edge of the system clock if the sampled values of m_y and m_z are 0 and 2 respectively, Vera increments the hit count for bin s1 of cross cc1 (regardless of the sampled value for g_var1). For example, for following set of sampled values, Vera will increment state s1: - m_y = 0, m_z = 2, g_var1 = 12 - m_y = 0, m_z = 2, g_var1 = 1 When the coverage points are sampled, if the expression associated with a user defined cross state does not evaluate to true, Vera creates an automatic cross product bin for the state and/or transition bins that are hit in each coverage point. In Example 7-25, when the sampled value of m_y, m_z, and g_var1 are 1, 2, and 12 respectively, Vera creates an automatic bin for the cross product of bins that are hit in each sampled variable.

Functional Coverage 7-128

Valid Expressions for Defining Cross Coverage Bins Although Vera allows for the use of expressions in a cross coverage bin specification, there are certain kinds of expressions that are not allowed and flagged as semantic errors by the Vera compiler. Validity of expressions used in cross coverage bin specification is governed by the following three rules: Definition of the cross bin (in terms of the range of values of the crossed coverage point) should not change in every sample. Otherwise, coverage number computation will be very expensive, and even impossible in certain cases. Since tasks and functions can be blocking, you cannot use task or function calls. A sample name associated with a sampled expression can be used in the expression, provided it is present in the list of samples for the cross.

The first rule implies that each sub-expression must contain only one crossed coverage point. Example 7-56 involves two invalid expressions (flagged as errors by the Vera Compiler), and two valid expressions

Example 7-56
coverage_group cov1 { sample_event = @(posedge CLOCK); sample m_x, m_y, g_var1; cross cc1(m_y, m_z) { ignored invalid1 (m_y > m_z); ignored invalid2 (m_y + m_z == 2); ignored ok1 (m_y * 2 > 24); ignored ok2 (m_y * 2 < g_var1); state s1 (m_y == 0 && m_z == 2); } }

Functional Coverage 7-129

The expression used in the ignored state invalid1 uses the crossed sampled variables on both sides of the relational operator >. The expression used in ignored state invalid2 uses both of the sampled variables in its + sub-expression. The expressions used for ok1 and ok2 are valid since they do not use more than one of the crossed sampled variables in their sub-expressions. In Example 7-56, the expression m_y == 0 && m_z == 2 (used for defining cross coverage bin s1) conjoins two sub-expressions m_y == 0 and m_z == 2. Each sub-expression has only one sampled variable on each side of the relational. The expression is therefore valid. An invalid expression would be m_y <= m_z && m_z == 2. In that case, the first sub-expression (m_y <= m_z) has the sampled variables on both sides of the relational. If a non-sampled variable is used in a cross bin expression (for example, g_var1 in the example above), Vera evaluates the expression using the value of the variable at the time that the coverage_group is instantiated.

Enhancements to cross coverage


When defining a cross, you can define named cross product bins that correspond to illegal, ignored, or user-specific cross products. A cross product that matches an illegal user-defined cross product bin causes a verification error. Otherwise, if the cross product matches an ignored user-defined bin, the coverage engine skips the cross (for that particular sampling event). Otherwise, if the cross product matches a user-defined (state) cross product bin, the coverage engine increments the hit count for that bin. Otherwise, the coverage engine automatically creates a cross-product bin

Functional Coverage 7-130

(auto-cross-product bin) for that cross product. The following two enhancements are related to the creation/printing of auto-cross-product bins. Saving/reporting missing cross product bins Disabling generation of automatic cross product bins

Saving/reporting missing cross product bins


In Vera 6.0, the functional coverage engine creates auto-cross-product bins solely for cross-products that are observed during the simulation.

Example 7-57
coverage_group Cov { sample_event = @(posedge CLOCK); sample x { state sx_1(4'h1), sx_2(4'h2); trans tx_1_2(4'h1->4'h2); } sample y { state sy_a(4'ha), sy_b(4'hb); trans tx_a_b(4'ha->4'hb); } cross cc1 (x,y); } program test { bit [3:0] x, y; Cov cov = new; @(posedge CLOCK); x= 4'h1; y= 4'ha; @(posedge CLOCK); x= 4'h2; @(posedge CLOCK); }

Functional Coverage 7-131

In Example 7-57, there are nine auto-cross-product bins that can possibly be created by the coverage engine for cross cc1. However, The testbench only exercises three of the six cross products leading to the following report:
CoverageGroup: Cov Cross: cc1 Summary Coverage: 33.33 Goal: 90 Number of Samples Crossed: 2 Samples Crossed: x y Number of Expected Cross Bins: 9 Number of User Defined Cross Bins: 0 Number of Automatically Generated Cross Bins: 3 Number of Missing Cross Bins: 6 Automatically Generated Cross Bins x y # hits at least ======================================================= sx_1 sy_a 1 1 sx_2 sy_a 1 1 tx_1_2 sy_a 1 1 =======================================================

In Vera 6.0, there is no way to print the missing cross products (missing auto-cross-product bins). cross_num_print_missing

In Vera 6.1 you can specify the number of missing (not created) auto-cross-product bins that should be printed by the coverage engine. This is controlled by the cross_num_print_missing attribute. The attribute can be set for a particular cross or for the coverage_group as a whole (affecting all crosses of the coverage_group).

Functional Coverage 7-132

Syntax
cross_num_print_missing = expression;

expression
Is any Vera expression that evaluates to an integer (greater than or equal to zero). The expression may not include any task or function calls other than the coverage_group query() or inst_query() built-in functions. The expression is evaluated at the time that a coverage_group is instantiated. If the attribute is greater than zero, then it specifies the number of missing auto-cross-product bins that the Vera coverage engine saves to the database. If the above coverage_group definition is modified as follows, then two of the missing six auto-cross-product bins are printed.

Example 7-58
coverage_group Cov { sample x { state sx_1(4'h1), sx_2(4'h2); trans tx_1_2(4'h1->4'h2); } sample y { state sy_a(4'ha), sy_b(4'hb); trans tx_a_b(4'ha->4'hb); } cross cc1 (x,y); sample_event = @(posedge CLOCK); // save/print 2 of the missing auto-cross-product // bins cross_num_print_missing = 2; }

Functional Coverage 7-133

The coverage report for the modified coverage_group definition now includes the following information:
Missing Cross Bins x y # hits at least ======================================================= sx_1 sy_b 0 1 sx_1 tx_a_b 0 1 =======================================================

For Example 7-58, if the cross_num_print_missing attribute is set to:


cross_num_print_missing = (1 << 32)-1; // INT_MAX

then all missing auto-cross-product bins are printed, and the report for Example 7-58 would include the following information:
Missing Cross Bins x y # hits at least ======================================================= sx_1 sy_b 0 1 sx_1 tx_a_b 0 1 sx_2 sy_b 0 1 sx_2 tx_a_b 0 1 tx_1_2 sy_b 0 1 tx_1_2 tx_a_b 0 1 =======================================================

Disabling generation of automatic cross product bins


Bins In Vera 6.0, any cross products that do not match a user-defined cross bin are automatically binned into an auto-cross-product bin. There are, however, situations where the user would like Vera coverage to only consider the user-defined cross bins, and avoid

Functional Coverage 7-134

creating any auto-cross-product bins. Alternately the user may want to limit the number of auto-cross-product bins that are created by the coverage engine. Example 7-59 illustrates the point.

Example 7-59
coverage_group Cov { sample_event = @(posedge CLOCK); sample x,y; cross cc1 (x,y){ state sx0(x==0); state sx1(x==1); } } program test { bit [2:0] x,y; Cov c = new; @(posedge CLOCK); x=3'b0; y=3'b100; // sx0 gets a hit @(posedge CLOCK); x=3'b010; y=3'b101; // automatic cross product bin (s_2,s_5) @(posedge CLOCK); x=3'b011; y=3'b101; // automatic cross product bin (s_3,s_5) @(posedge CLOCK); x=3'b001; y=3'b001; // sx1 gets a hit @(posedge CLOCK); }

In Vera 6.0, the following report is generated for Example 7-59, where two auto-cross-product bins are created for cross-products of variable x and y that do not match the user defined cross bins sx0 and sx1. Note that a total of 66 cross product bins should to

Functional Coverage 7-135

be created (two user defined bins, and 64 auto-cross-product bins associated with the 23 * 23 cross products of x and ythese variables are 3 bit bit-vectors).
Cross: cc1 Summary Coverage: 6.06 Goal: 90 Number of Samples Crossed: 2 Samples Crossed: x y Number of Expected Cross Bins: 66 Number of User Defined Cross Bins: 2 Number of Automatically Generated Cross Bins: 2 User Defined Cross Bins Bin # hits at least ========================================================== sx0 1 1 sx1 1 1 ========================================================== Automatically Generated Cross Bins x y # hits at least ======================================================= s_2 s_5 1 1 s_3 s_5 1 1 =======================================================

cross_auto_bin_max

In Vera 6.1 a mechanism was introduced for controlling the maximum number auto-cross-product bins created by the coverage engine. This is controlled by the cross_auto_bin_max attribute. This attribute can be set for a particular cross or for the coverage_group as a whole (affecting all crosses of the coverage_group).

Functional Coverage 7-136

Syntax
cross_auto_bin_max = expression;

expression
Is any Vera expression that evaluates to an integer (greater than or equal to zero). The expression may not include any task or function calls other than the coverage_group query() or inst_query() built-in functions. The expression is evaluated at the time the coverage_group is instantiated. If the attribute is greater than or equal to zero, it specifies the maximum number of automatically generated cross product bins that the Vera coverage engine will create for a cross. If the above coverage_group definition is modified as follows, then we create only one auto-cross-product bin.

Example 7-60
coverage_group Cov { sample x,y; cross cc1 (x,y){ state sx0(x==3'b0); state sx1(x==3'b001); } cross_auto_bin_max = 1; sample_event = @(posedge CLOCK); }

The cross coverage report for the modified example would then look as follows. Note that since the maximum number automatically generated cross product bins is set to 1, we now expect a maximum of 3 cross product bins (2 user defined, and 1 auto). The example, therefore, gives 100 percent coverage.

Functional Coverage 7-137

Cross Coverage report CoverageGroup: Cov Cross: cc1 Summary Coverage: 100.00 Goal: 90 Number of Samples Crossed: 2 Samples Crossed: x y Number of Expected Cross Bins: 3 Number of User Defined Cross Bins: 2 Number of Automatically Generated Cross Bins: 1 User Defined Cross Bins Bin # hits at least ========================================================== sx0 1 1 sx1 1 1 ========================================================== Automatically Generated Cross Bins x y # hits at least ======================================================= s_2 s_5 1 1 =======================================================

Coverage Group Attributes


cross_bin_max: The cross_bin_max attribute is used for computing the coverage number for a cross. It specifies the maximum number of cross coverage bins expected in a cross. By default, the number of possible bins for a cross is the sum of the user-defined bins and the number of possible automatically generated bins. The number of possible automatically generated bins is the product of the number of possible bins for each of the samples being crossed. If cross_bin_max is set, its value will be used as the upper-bound for the number of possible bins in a cross.

Functional Coverage 7-138

Example 7-61 default


#include <vera_defines.vrh> coverage_group router_cov() { sample_event = wait_var(port_event) async; sample ip; sample op; cross port_cross(ip, op); } program test { integer port_event = 0; integer i, j; integer ip = 0; integer op = 0; router_cov port_fc=new(); for(i=0; i<1000; i++) { for(j=0; j<1000; j++) { ip = i; op = j; port_event++; } } }

Since the default auto_bin_max setting for the sample ip and sample op is 64, the cross_bin_max value in Example 7-61 is 4096 (64x64). If auto_bin_max for ip and op is changed to the maximum value, the cross_bin_max value will increase accordingly. cross_num_print_missing: This attribute controls the number of missing (not created) auto-cross-product bins that should be printed by the coverage engine. If the attribute is greater than zero, then it specifies the number of missing auto-cross-product bins the Vera coverage engine saves to the database. Please refer to Cross Coverage Definition.

Functional Coverage 7-139

Functional Coverage 7-140

8
Reference Verification Methodology (RVM) 8
Vera's reference verification methodology enables users to realize the full potential of a coverage-driven, constrained-random flow. In addition to documenting testbench architecture, modeling, and coding guidelines, Vera's support of the reference verification methodology includes testbench building blocks (base class libraries) that provide a solid foundation for building an advanced verification environment, and example designs to see the methodology and building blocks in use. For more information, please refer to the Reference Verification Methodology User Guide.

8-1

Reference Verification Methodology (RVM) 8-2

9
Temporal Assertions and Expressions 9
OpenVera provides three pre-defined classes that enable the interaction of testbenches with OpenVera temporal expressions and assertions (OVA). Instances of these classes (that is, the objects) are used to: take action on assertions and expressions, synchronize threads with assertion and expression events,

provide access to assertion and expression events.

Table 9-1 OpenVera Assertion Classes


Object
OVAEngine

Description
monitors and controls OVA as a whole: -affects all assertions -resets and disables assertion attempts -controls information displayed at runtime and in the report file monitors and controls individual assertions and expressions: -affects only a specific assertion or expression -resets and disables assertion attempts synchronizes the testbench with events in OVA -suspends a thread of the testbench

OVAAssert

OVAEvent

Table 9-2 gives the definition of the operations that can be performed on assertions (reset, disable and suspend).

Table 9-2 Assertion Operations


Action
reset

Affect
Resetting ends all attempts to match assertions and expressions immediately and without results. New attempts start normally with the next clock cycle. Disabling ends all current attempts and prevents new attempts from starting. Suspending a thread suspends the thread until the object is triggered by its event.

disable suspend

Figure 9-1 shows a typical simulation runtime environment with Vera testbenches (*.vr) interacting with the OVA assertion files (*.ova). Note: In this chapter the term assertion refers to an assert declaration in a .ova file, and not to an object of the Vera class type, OVAAssert. Further, the term expression is used here to refer to either a bool or event declaration in a .ova file.

Temporal Assertions and Expressions 9-2

Figure 9-1 Interaction of OVA Objects


V E RA Testbench (*.vr) Actions Triggers

O VAE ngine OVAE vent Event

Assertions File (*.ova)

Actions Triggers

O VAA ssert assertion1 OVAE vent Event

assertion1

Actions expressi on2 Triggers

OVAA ssert expression2 OVAE vent Event

OVAE vent Results

Event

Typically, you will have the following: an OVAEngine object for each Vera program file, an OVAAssert object for every assertion and expression used in the testbench, an OVAEvent object for every event being monitored.

Note: This is not the event as defined in OVA but rather as used in Vera. Here, an event is some occurrence that Vera can trigger on, such as a Failure or SUCCESS event.

Temporal Assertions and Expressions 9-3

For more information about OpenVera temporal expressions and assertions, see the OpenVera Language Reference Manual: Testbench (Chapter 12, Predefined Methods and Classes section entitled OpenVera Temporal Assertion Classes). (

Temporal Assertion Flow


Once you have developed an OpenVera Assertion file (typically a file.ova source file), you are ready to add the OVA Objects to your Vera testbench in order to access or monitor the assertions in that file.ova. The following section walks you through the steps, using an example testbench.

Adding OVA Objects to a Testbench


There are five major steps in adding OVA objects to a testbench: 1. Include the VeraOva.vrh header file 2. Set up the OVAEngine object. 3. Set up the OVAAssert objects. 4. Set up the OVAEvent objects. 5. (optionally) Terminate the OVAEngine object

Including the VeraOva.vrh Header File


To start, every file that instantiates an OVA object must include the header file that defines the classes:
#include <VeraOva.vrh>

Temporal Assertions and Expressions 9-4

Setting Up the OVAEngine Object


The program block must instantiate one, and only one, OVAEngine object. For a summary of the class and its methods, see the description of OVAEngine Class in the OpenVera Language Reference Manual.
program test{ ... OVAEngine ova_engine = new(); ... }

Controlling OVA Reporting


Once the engine is running, use its Configure() task to specify how OVA reports results. The testbench settings take priority over compiler and runtime switches. Example 9-1 instantiates the OVAEngine, turns off the OVA_QUIET option, thus turning on runtime messages, and turns on line information in the messages with the OVA_INFO option. The OVA_REPORT option, which generates the ova.report file, is on by default.

Example 9-1
program { ... OVAEngine ova_engine = new(); ova_engine.Configure(OVA_QUIET, OVA_FALSE); ova_engine.Configure(OVA_INFO, OVA_TRUE); }

Temporal Assertions and Expressions 9-5

Resetting OVA
At any time during the simulation, you can reset all attempts at matching assertions and expressions. You might want to reset when you switch to a new test and do not want to be confused by attempts started in the previous test. For example:
ova_engine.DoAction(OVA_RESET);

Setting Up the OVAAssert Objects


For every assertion and expression that is used by the testbench, the testbench needs an OVAAssert object. For a summary of the class and its methods, see the description of the OVAAssert Class in the OpenVera LRM: Testbench book.

Instantiating OVAAssert Objects


OVAAssert does not have a new() method. Instead, use OVAEngine functions to obtain handles to OVAAssert objects. You can specify the assertion or expression by the full hierarchical name. For example, for an assertion named check1 in a unit named test:

Example 9-2
OVAAssert ova_check1; ova_check1 = ova_engine.GetAssert("test.check1");

Note: The full hierarchical name may vary depending on the simulator. To obtain an example of the full hierarchical name for your simulator, use the GetFirstAssert() method of the OVAEngine class. This returns a handle for the first assertion in the design.

Temporal Assertions and Expressions 9-6

Print the name of this assertion using the GetName() method of the OVAAssert class to see how your simulator delimits the hierarchy. Another way is to create a loop and collect handles to all of the assertions and expressions. This way the number of assertions and their names can vary without changing the testbench. The GetFirstAssert() function can be used anytime to obtain the first assertion or expression in the compiled list. This is not necessarily the first in the OVA source file: the order might change while compiling. The GetNextAssert() function fetches more OVAAssert handles until it delivers a null, indicating the end of the list. Identify the handles with the OVAAssert objects GetName() function. In Example 9-3, the testbench sets up OVAAssert objects for all assertions and expressions, however many there might be:

Example 9-3
OVAAssert ova_check[]; string ova_name[]; int i = 0; ova_check[0] = ova_engine.GetFirstAssert() while (ova_check[i] != null){ ova_name[i] = ova_check[i].GetName(); ... ova_check[++i] = ova_engine.GetNextAssert(); }

This testbench also creates arrays of handles and names.

Temporal Assertions and Expressions 9-7

Controlling Evaluation Attempts


You can control attempts on individual assertions and expressions at any time during the simulation with the DoAction() task. For example, to reset attempts on the test.check1 assertion shown in the example in the previous section, you could use the following:
ova_check1.DoAction(OVA_RESET);

In OVA, expressions are often used as components in other expressions and assertions. For example:
event sig_pair: sig1 #1 sig2 assert check1: frame #1 sig_pair

Actions on component expressions do not affect other expressions and assertions (with one exception). For example, in the above OVA code, disabling attempts on expression sig_pair has no effect on evaluating assertion check1. The assertion is actually evaluating the sig_pair sequence independently of the expression. Before using DoAction(), consider if you are acting on an expression that is used with a matched operator. Disabling evaluation of the expression will mean that the matched operator will never generate its event. As a result any expression or assertion using that matched expression will fail. For example, in the following OVA code, assertion check1 fails if expression sig_pair is disabled:
event sig_pair: sig1 #1 sig2 assert check1: frame #1 matched sig_pair

Temporal Assertions and Expressions 9-8

Counting Successes and Failures


You can set up a running count of evaluation successes or failures. This does not need an OVAEvent object. To start the counting, just call the OVAAssert objects EnableCount() task. To see the current value, call the objects GetCount() function. In Example 9-4, the code keeps track of how many times the assertion check1 fails and generates an error, optionally ending the simulation, if there are too many failures:

Example 9-4
ova_check1.EnableCount(OVA_FAILURE); ... if (ova_check1.GetCount(OVA_FAILURE) > max_fail) error("Check1 exceeded failure limit.");

EnableCount() starts a running count that cannot be disabled or reset. To create a count that can be disabled or reset, set up an OVAEvent object (as explained in the following section) and create your own code to count the event triggers.

Setting Up the OVAEvent Objects


For every event being monitored, the testbench needs an OVAEvent object. For a summary of the class and its methods, see the description of the OVAEvent Class in chapter 12 in the OpenVera LRM:Testbench book.

Temporal Assertions and Expressions 9-9

Instantiating OVAEvent Objects


Instantiate an OVAEvent object with its new() task, including an event type. Then attach the object to an OVAEngine or OVAAssert object with that objects EnableTrigger() task. The event is not monitored until the EnableTrigger() task. For example, to monitor successful attempts on the check1 assertion, use the following:
OVAEvent check1_success = new(OVA_SUCCESS); ova_check1.EnableTrigger(check1_success);

Or, to watch for a global reset by the OVAEngine, use the following:
OVAEvent ova_engine_reset = new(OVA_RESET); ova_engine.EnableTrigger(ova_engine_reset);

Each OVAEvent object can be used with only one OVAEngine or OVAAssert object. For example, to watch for OVA_SUCCESS on three assertions, you must create three OVAEvent objects and attach each one to a different OVAAssert object.

Suspending Threads
OVAEvent objects are normally used to suspend a thread until the event happens. There are two ways to do this: the objects Wait() task or with Veras sync() task and the objects Event variable. For example, using the Wait() task to wait for a global reset action:
ova_engine_reset.Wait();

Using the sync() task:


sync(ALL, ova_engine_reset.Event);

Temporal Assertions and Expressions 9-10

After a thread resumes, you can see which events happened with the OVAEvent objects GetNextEvent() function. If called repeatedly, the function returns a list of events starting with the most recent and ending with OVA_NULL. For example:
reason = ova_engine_reset.GetNextEvent();

Eliminating OVAEvent Objects


When finished with an event, disable the trigger and recover the OVAEvent objects memory space with the associated OVAEngine or OVAAssert objects DisableTrigger() task.

Example 9-5
ova_engine.DisableTrigger(ova_engine_reset);

Terminating the OVAEngine


When the testbench is completely finished with OVA, it should terminate all OVA activity with the OVAEngines DoAction() task. This task also recovers the memory space of all the OVA objects.

Example 9-6
ova_engine.DoAction(OVA_TERMINATE);

Example Testbench
The following example shows a simple testbench that tests a traffic light controller. The testbench uses OVA objects to test for an error condition, both lights being green at the same time, and to track the cycles of the light.

Temporal Assertions and Expressions 9-11

Example 9-7 Example Testbench using Assertions


#include <vera_defines.vrh> #include <VeraOva.vrh> #include "traffic.if.vrh" program traffic_test { OVAEngine ova_engine; OVAAssert ova_assert_both_green, ova_assert_count; OVAEvent ova_event_both_green; ova_engine = new();// Instantiate OVAEngine // Instantiate one OVAAssert per assertion. ova_assert_both_green = ova_engine.GetAssert ("traffic_test_top.dut.a_both_green"); ova_assert_count = ova_engine.GetAssert ("traffic_test_top.dut.a_light0_cycle"); // Track the number of times the lights cycle // green->yellow->red. ova_assert_count.EnableCount(OVA_SUCCESS); // Instantiate OVAEvents. ova_event_both_green = new(OVA_FAILURE); // Attach OVAEvent to an OVAAssert. ova_assert_both_green.EnableTrigger(ova_event_both_green); // Fork off 2 threads - 1 to reset circuit, 1 to // stop if error occurs. fork // Reset the traffic light { traffic.rst = 1 async; @1 traffic.rst = 0; } // Stop if both traffic lights are green. { ova_event_both_green.Wait(); error("Both lights are green.\n"); } join none repeat(20) @(posedge traffic.clk); printf("Light0 cycled %0d times.\n", ova_assert_count.GetCount(OVA_SUCCESS)); }

Temporal Assertions and Expressions 9-12

In Example 9-7, we have two assertion expressions that are defined in the .ova file: a_both_green and a_light_0cycle. We want to monitor them in Vera. The OVAEngine is instantiated and is newed. We instantiate one OVAAssert per assertion and use GetAssert to connect to the assertion. For instance, the OVAAssert, ova_assert_both_green, is associated with the a_both_green assertion. Once the OVAEvent is instantiated, we can monitor the assertion and react to events associated with it. Note: Refer to the Vera installation examples directory README file in the location of OVA examples within the examples directory.

Compiling and Simulating OVA Objects


Like OVA Assertions, OVA Objects support all the simulators currently supported by Vera. For a list of these simulators, see the Vera Configuration Guide or the Vera Release Notes. In order to run with VCS, no additional step is required to compile the OVA Objects. However to run the OVA Objects with a third party simulator, there is an additional step to follow.

Running a Vera Simulation with OVA


After the OVA files are written and compiled, an OVA shared object file is created and dynamically linked to the simulation. The OVA assertions are automatically linked to the Vera OVA engine during simulation. The flows for each simulator are described later in this

Temporal Assertions and Expressions 9-13

section. Because the checkers are compiled independently of any simulator, they can also be packaged with IP designs and shipped to any customer using any of the major simulators.

Getting Started
Summary of Simulation of Vera/OVA 1. Create OVA Checkers Create the OVA checkers as described in the chapter entitled, Using OpenVera Assertions of the VCS User Guide v7.2. 2. Compile OVA Checkers Then compile the OVA code with Vera to produce the Vera shell file and the shared object. Linking the assertions to the design is automatically done by the Vera shell file. The Vera compiler can now be invoked for compilation of multiple ova files. All ova files, ova options and simulator options specified by the user at command line will be passed to the OVAsim binary

The OVAsim Flow


A major enhancement in Vera 6.2 over Vera 6.1 is that a separate OVAsim wrapper is no longer created, so the wrapper file does not need to be instantiated in the netlist (For documentation of the previous flow, see pre-6.2 versions of the Vera User Guide). In line with this enhancement is a new OVAsim compile option, -ova. For instance:
vera -cmp -vlog -ova test.vr

Temporal Assertions and Expressions 9-14

Vera will generate the test.vro as usual. But, the generated Vera shell file (that is, test_shell.v), in addition to the regular vera_shell module, will have the definition of the OVAsim standard installation shell module. The Vera shell of VHDL simulators (except Scirocco) will contain the definition of the standard OVAsim wrapper entity. OVAsim Platform and third party simulator support (see the Vera Configuration Guide for version numbers): Supported Platforms for OVAsim flow SOL, HP, LINUX Note: 32-bit platforms only Supported third party simulators for OVAsim flow NC-Verilog for Verilog simulation Modelsim for Verilog simulation Modelsim for VHDL simulation

OVA/OVAsim Limitations NC_VHDL is not supported in Vera 6.2.0 and later versions. Vera 6.2.0 OVAsim will not work for prior versions of Vera.

Old limitations that have been removed More than one unit definition is now supported Unit parameters for the assertions can now be overridden by the design

Temporal Assertions and Expressions 9-15

Supported Platforms by Synopsys Simulator VCS support on HP_UX, Linux, and Solaris (DEC Alpha & AIX are not supported) VCS-MX (pure VHDL flow) support on Solaris, HP_UX and Linux VCS-MX (mixed HDL flow) with Verilog on Top support for Solaris, HP_UX and Linux VCS-MX (mixed HDL flow) with VHDL on Top support for Solaris, HP_UX and Linux

Further discussion The Vera shell file will contain the definition of the OVAsim standard installation wrapper module or wrapper entity, architecture pair.

-ova option
The new OVAsim compile option, -ova, has been introduced to the OVAsim flow.
vera -ova simulator simulator_options

This option causes Vera to generate a test_shell.v file for the Verilog simulator, or a test_shell.vhd for the Modelsim Verilog simulator containing the definition of the OVAsim wrapper.

New Vera-OVASIM Flow with Different Simulators


Vera and NC-Verilog
vera -cmp -ova -vlog test.vr vera -cmp test.ova vera -cmp a.ova b.ova c.ova // compiling multiple files CreateLibVpi ncprep test.v test_shell.v +overwrite ncvlog -f ncvlog.args

Temporal Assertions and Expressions 9-16

ncelab -f ncelab.args -access +rcw vera -ova ncsim -f ncsim.args +vera_load=test.vro ncsim -f ncsim.args +vera_load=test.vro

Vera and MTI-Verilog


vera -cmp -ova -vlog test.vr vera -cmp test.ova vera -cmp a.ova b.ova c.ova // compiling multiple files CreateVeriuser setenv PLIOBJS ./veriuser.so vlib work vlog *.v test_shell.v vera -ova vsim test ovasim_wrapper -c -do \ "run -a;quit" +vera_load=test.vro vsim -do "run -all;quit" -c test ovasim_wrapper +vera_load=test.vro

Vera and MTI-VHDL


vera vlib vera vera vcom vera -cmp -mti -ova test.vr work -cmp -mti test.ova -cmp -mti a.ova b.ova c.ova // compiling multiple files test.vhd test_shell.vhd -ova vsim -c test ovasim_wrapper \ -do "run -all;quit" vsim -c test ovasim_wrapper -do "run -all; quit"

Vera and Scirocco


vera -cmp -sro test.vr vera -cmp -sro purevhdl.ova vera -cmp -sro a.ova b.ova c.ova // compiling multiple files vhdlan test_shell.vhd test.vhd scs -ova test scsim -R

Vera and MX (VHDL top)


vera -cmp -sro test.vr vera -cmp -sro test.ova vera -cmp -sro a.ova b.ova c.ova // compiling multiple files vlogan test.v vhdlan test_shell.vhd test.vhd scs -ova test -verilogcomp "+cli+4" scsim -R

Temporal Assertions and Expressions 9-17

Vera and MX (Verilog on top)


vera -cmp -vcs_mx test.vr vera -cmp test.ova vera -cmp a.ova b.ova c.ova // compiling multiple files vhdlan test.vhd vcs -mhdl -ova_mhdl -vera test_shell.v test.v simv

Limitations
The OVAsim flow for Vera 6.2.0 is not supported for NC-VHDL. NC-VHDL users will have to use Vera 6.0 in order to simulate OVA.

Task Invocation from the Simulators Prompt


OVA system tasks can be called from the simulators prompt. With Verilog simulators:
$ova_stop levels

Applied down to depth levels with respect to the present scope.


$ova_start levels modname

Applied to all instances of module modname down to a depth of levels. Note that no XMR is allowed, however module names are allowed without a quoted string. The commands can also be issued using the format used in task calls, that is, arguments in parentheses separated by commas. Module names must be quoted as in the task calls.

Temporal Assertions and Expressions 9-18

With VHDL simulators:


ova_start [levels [entity or scope arguments]] ova_stop [levels [entity or scope arguments]] ovadumpon ovadumpoff

Viewing Results with the Report File


A report file is created when the -ova_report runtime option is used. The reports file name is ova.report unless you specified a different name in the run command. This default ova.report file is stored in directory simv.vdb/report (with Verilog) or simv.o.vdb/report (with VHDL), where the .vdb directory is the root directory at the same level where the design is compiled. To override this default name and location for the report file, use the -ova_report runtime option and provide the full path name of the report file. The report file is replaced with each simulation run. If you want to save the results, be sure to rename the file before running the simulation again. Assertion attempts generate messages with the format shown in Figure 9-2.

Figure 9-2 Assertion Message Format


Severity File and line with the assertion Full hierarchical name of the assertion Start time Status (succeeded at ..., failed at ..., not finished)

Ova [0]: "cnt.ova", 10: cnt.dut.c_normal_s: started at 5ns failed at 9ns, "Wrong outp sequence.", Offending 'outp == 4 #1 outp == 6 #1 outp == 9 #1 outp == 3'
Optional user-defined failure message Expression that failed (only with failure of check assertions)

Temporal Assertions and Expressions 9-19

Using OVA Assertions with Vera and Third Party Simulators


This section describes the use of OVAsim with various simulators. Topics covered include: OVA with Synopsys Simulators OVAsim with NC-Verilog, NC-VHDL OVAsim with MT Verilog, MTI-VHDL

Compiling and Simulating with VCS


1. Compile the testbench.
vera -cmp -vlog test.vr

2. 2. Compile the design with the Vera testbench and OVA files
-vcs -vera test.v test_shell.v test.ova

Note:

see vera_dbind and vera

3. Run the simulation.


vsim -do "run -all;quit" -c cfg_tb ovasim_wrapper

Vera and VCS MX simulation Verilog top


This simulation involves a Vera and VCS MX simulation Verilog top, OVA assertions connecting to pure Verilog 1. Compile the testbench
vera -cmp -vcs_mx interface.vr

Temporal Assertions and Expressions 9-20

2. 2. Compile the OVA file


-vera -cmp purevlog.ova

3. Analyze the VHDL files


mkdir work vhdlan purevhdl.vhd

4. Elaborate the design


vcs -mhdl -vhdlelab "-vhpi ovasim_pli_mx:ovasim_elab_bind \ -vhpi ovasim_pli_mx:ovasim_init_bind" -vera interface.vshell \ top.v

5.
vera -ova -sro simv

6. Run the simulation


simv

Vera and VCS MX simulation


This is for a VHDL instantiated in Verilog top, OVA assertions connecting to pure VHDL. 1. Compile the testbench
vera -vcs_mx -cmp interface.vr

2. Compile the OVA file:


vera -cmp purevhdl.ova

3. Analyze the VHDL design


vhdlan purevhdl.vhd

4. Elaborate the design


vcs -mhdl -vhdlelab "-vhpi ovasim_pli_mx:ovasim_elab_bind \

Temporal Assertions and Expressions 9-21

-vhpi ovasim_pli_mx:ovasim_init_bind" -vera interface.vshell \ top.v

5.
vera -ova -sro simv

6. Simulate
simv

Compiling and Simulating with NC-Verilog


1. Compile the OVA files
vera -cmp ova_files [ova_options]

2. Compile the Vera testbench


vera -cmp -vlog -ova test.vr

Note: -ova should always be after -cmp in the command line 3. Compile the design with the testbench
ncprep test.v test_shell.v ncvlog -f ncvlog.args ncelab -f ncelab.args -access +r vera -ova ncsim -f ncsim.args +vera_load=test.vro

Note: -cmp is not used in the Vera command line 4. Define the OVA runtime flags
setenv OVASIM_RUNTIME_FLAGS ova_runtime_flags

5. Run the simulation


ncsim -f ncsim.args +vera_load=test.vro

Temporal Assertions and Expressions 9-22

Compiling and Simulating with NC-VHDL


Note: VCS 7.1 and Vera6.2.0 do not support the new OVAsim use model with binding for NC-VHDL. The old OVAsim use model is supported with releases prior to VCS7.1 and Vera6.2.0. You have to use prior VCS and Vera versions to use the old flow. You have to instantiate the OVAsim generated shell to run OVAsim with NC-VHDL. 1. Compile the OVA files
vera -cmp -nc_vhdl ova_files [ova_options]

2. Compile the Vera testbench


vera -cmp -voa -nc_vhdl test.vr

3. Create the working directory, then compile the design and testbench
mkdir work ncvhdl test.vhd test_shell.vhd ncelab -access +rw -nostdout cfg_tb vera -ova ncsim -i nctest.in

4. Define the OVA runtime flags


setenv OVASIM_RUNTIME_FLAGS ova_runtime_flags

5. Run the simulation


ncsim -i nctest.in cfg_tb

Temporal Assertions and Expressions 9-23

Compiling and Simulating with MTI Verilog


1. Compile the OVA files
vera -cmp ova_files [ova_options]

2. Compile the Vera testbench


vera -cmp -ova -vlog test.vr

3. Compile the design with the testbench Create veriuser.so


vlib work vlog test.v test_shell.v vera -voa vsim -c test +vera_load=test.vro -pli \ ./path_to/veriuser.so

4. Define the OVA runtime flags


setenv OVASIM_RUNTIME_FLAGS "ova_runtime_flags"

5. Run the simulation


vsim -do "run -all;quit" -c test +vera_load=test.vro \ -pli ./path_to/veriuser.so

Temporal Assertions and Expressions 9-24

Compiling and Simulating with MTI VHDL


1. Compile the OVA files
vera -cmp -mti ova_files [ova_options]

2. Compile the Vera testbench


vera -cmp -mti -ova test.vr

3. Create the working directory, then compile the design with the testbench
vlib work vcom test.vrh test_shell.vhd vera -ova vsim -c cfg_tb ovasim_wrapper

4. Define the OVA runtime flags


setenv OVASIM_RUNTIME_FLAGS "-ova_runtime_flags"

5. Run the simulation


vsim -do "run -all;quit" -c cfg_tb ovasim_wrapper

Temporal Assertions and Expressions 9-25

Temporal Assertions and Expressions 9-26

10
Testbench Optimization 10
Vera provides a set of features to analyze a testbench, identifying potential areas of improvement, and to partition the simulation run, reducing overall simulation time. Vera Performance Profiler Vera Memory Profiler Save and Restart Dynamic Loading of Vera Object Files

Testbench Optimization 10-1

Vera Performance Profiler


The Vera Performance Profiler aids in writing more efficient OpenVera code. When performance profiling is turned on, Vera tracks: the time spent in each function, task and program, the time spent in the HDL simulator and in Vera internal, number of times each task or function is called, DirectC calls, UDF calls

The Vera performance and memory profilers can be enabled simultaneously. For example:
vera_cs test.vro +vera_profile_start +vera_profile_object

When time profiling is enabled, the simulation may noticeably slow down. Vera and VCS time profiling must not be used together.

Profiling Setup
The vera_report_profile() system task can be called anywhere in an OpenVera program. When the task is called, and the runtime option vera_profile_start is set, a profiling log file is generated, which reports information up to the task call. Incremental profiling results are, therefore, provided. The syntax for vera_report_profile() is:
task vera_report_profile( integer vera_profile_type, string filename);

Testbench Optimization 10-2

where:

vera_profile_type:
Specifies the type of Vera profiling. The valid value for performance profiling is VERA_PROFILE.

filename:
Is the name of the file in which the profiler data are recorded. If it contains a directory path that is incorrect, a warning message is issued, and the profiling results are stored in the default log file (vera.prof). Vera provides a set of runtime options that enable and control profiling. vera_profile_start vera_profile_limit vera_profile_filename vera_profile_sort_by_name

These options can be specified either in the command line or in the vera.ini file. Command line example:
+vera_profile_start +vera_profile_limit=1000

vera.ini file example:


// vera.ini file vera_profile_start vera_profile_limit=1000

Testbench Optimization 10-3

vera_profile_start
Enables performance profiling.

vera_profile_limit
Changes the default limit for tracking function, task and program calls. The Profiler, by default, tracks the first 500 functions, tasks and programs that are called. Any functions, tasks and programs called after the 500 limit is reached are grouped together. A statement is placed at the top of the log file indicating the time spent on these calls. The following example sets the limit to 1,000 calls:
+vera_profile_limit=1000

vera_profile_filename
Overrides the default profiling log file name. The default performance profiling log file name is "vera.prof." The following example creates a profiling log file called my.log:
+vera_profile_filename=my.log

vera_profile_sort_by_name
Sorts the profiling log file entries by the function, task and program name. By default they are sorted from the highest to the lowest percentage of runtime used.

Performance Profiler Example


The Vera performance profiler is illustrated here by means of a simple example. Program MyTest calls a Vera task MyPrint, and a DirectC task DirectC_call, together in a loop 20 times. The profiler reports the relative portion of the runtime that each consumes.

Testbench Optimization 10-4

Example 10-1 mytest.vr


#include <vera_defines.vrh> // declare DirectC tasks extern "C" task DirectC_call(integer a, integer b); task MyPrint(integer a){ printf("Inside MyPrint task with a = %d\n", a); } program MyTest{ integer k = 0; repeat (20){ @(posedge CLOCK); k = k + 1; MyPrint(k); DirectC_call(1, 2); } @(posedge CLOCK); }

Example 10-2 directC.c


#include "vera_user.h" #include "vera_exp_task.h" static int tmp; static void do_activity(int j){ int i; for( i = 0; i < 1000; i++ ) { tmp ^= j + i; } } void DirectC_call(int a, int b){ int i; for( i = 0; i < 1000; i++ ){ i +=b; i *=a; do_activity( i ); } }

Testbench Optimization 10-5

Example 10-3 Log File (vera.prof)


======================================================================== Vera Time Profiler ====================================================================== Current Simulation Time: 2050 Cycle Count: 21 Simulation Summary --------------------------------------------------------------------Current Percentage Breakdown of Total Time: HDL Simulator: 0.00 Vera Internal: 8.51 Vera Simulation: 91.49 Function/Task/Program --------------------------------------------------------------------Name %Totaltime No. of calls --------------------------------------------------------------------DirectC_call 85.11 20 --------------------------------------------------------------------MyPrint 6.38 20 --------------------------------------------------------------------MyTest 0.00 1 ----------------------------------------------------------------------------------------------------------------------------------------Total: 91.49 41 ---------------------------------------------------------------------

The profiling log file shown in Example 10-3 reports: The DirectC_call task (defined in DirectC.c) was called 20 times and consumed 85.01% of the simulation time The MyPrint task was called 20 times and consumed 6.38% of the simulation time The main program MyTest was called once and consumed 0.10% of the simulation time.

The time reported for any function, task or program is the time spent only in the immediate code. Time spent in descendants is not reported.

Testbench Optimization 10-6

Vera Memory Profiler


The Vera Memory Profiler aids in writing more efficient OpenVera code. The profiling results enable users, especially those unfamiliar with the testbench, to easily identify unexpected retention of OpenVera objects and threads. Furthermore, the profiling results can be used to verify that objects and threads are created in the expected number and at the expected time. When memory profiling is turned on, Vera tracks: The allocation and usage details regions, semaphores and mailboxes, The creation and completion of contexts, The mailbox created with their ID and count of their constituent elements, The dynamic array statistics with array names, array type, data type and array elements that are created, The allocation and automatic garbage collection of class objects.

The Vera performance and memory profilers can be enabled simultaneously. For example, by entering the following command:
vera_cs test.vro +vera_profile_start +vera_profile_object

When memory profiling is enabled, the simulation may noticeably slow down.

Testbench Optimization 10-7

Profiling Setup
The vera_report_profile() system task can be called anywhere in an OpenVera program. When the task is called, and the runtime option vera_profile_object or vera_profile_object_verbose is set, a profiling log file is generated, which reports information up to the task call. Incremental profiling results are, therefore, provided. By default, a memory profiling log file is generated at the end of a simulation. The syntax for vera_report_profile() is:
task vera_report_profile(integer vera_profile_type, string filename);

vera_profile_type:
Specifies the type of Vera profiling. The valid value for memory profiling is VERA_OBJECT.

filename:
The name of the file in which the profiler data are recorded. If it contains a directory path that is incorrect, a warning message is issued, and the profiling results are stored in the default log file (vera.object). Vera provides a set of runtime options that enable and control profiling. vera_profile_object vera_profile_object_verbose vera_object_filename

These options can be specified either in the command line or in the vera.ini file.

Testbench Optimization 10-8

Command line example:


simv +vera_profile_object

vera.ini file example:


// vera.ini file vera_profile_object

vera_profile_object
Enables memory profiling. Note: vera_profile_object and vera_profile_object_verbose are mutually exclusive. If both are specified, vera_profile_object takes precedence and the unfreed object trace table is not included.

vera_profile_object_verbose
Causes an unfreed object trace table is included in the memory profiling log file. Note: vera_profile_object_verbose and vera_profile_object are mutually exclusive. If both are specified, vera_profile_object takes precedence and the unfreed object trace table is not included.

vera_object_filename
Overrides the default filename. The default memory profiling log file name is "vera.object."

Testbench Optimization 10-9

Profiled Data Types


Table 10-1 shows the statistics that are reported for each data type the Vera profiler monitors.

Table 10-1 Data Types Profiled


Data Type
semaphores

What is Printed in the Log File


For each semaphore alloc(): - the maximum number of semaphores initially allocated, (Note: The default number is 2048. Using the Vera runtime option, vera_semaphore_size, this default value can be overridden.) - the number of semaphores that are allocated, or currently in use For each region alloc(): - the maximum allowed number of regions initially allocated, (Note: The default number is 256. Using the Vera runtime option, vera_region_size, this default value can be overridden.) - the number of regions that are allocated, or currently in use For each mailbox alloc(): -the maximum allowed number of mailboxes initially allocated,(Note: The default number is 256, Using the Vera runtime option, vera_mailbox_size, this default value can be overridden.) -the number of mailboxes that are allocated, or currently in use -the -the -the -the any number of threads number of threads number of threads maximum number of given instance of created, finished, remaining, threads that are running at time

regions

mailboxes

fork/join

Testbench Optimization 10-10

Table 10-1 Data Types Profiled (Continued)


Data Type
class objects

What is Printed in the Log File


For each class that is allocated: -the class name, -the total number of objects of this class are new()ed, -the total number of objects of this class are garbage collected, -the total number of objects of this class are not garbage collected For each dynamic array that is created: -the array name, -the array type, -the array element data type, -the total count of elements in the array For each mailbox that is created: -the constituent element ID, -the total count of constituent elements created for each mailbox

dynamic arrays statistics

mailbox

Testbench Optimization 10-11

Memory Profiler Example


The runtime command
vera_cs test.vro +vera_profile_object

generates the following memory profiling log file named vera.object shown in Example 10-4.

Example 10-4 Memory Profiling Log File


============================================================================ Vera Object Profiler End of Simulation Report ============================================================================ Simulation Time: 250 Cycle Count: 3 Semaphore/Region/Mailbox ---------------------------------------------------------------------------Type Max. no. of objects No. of objects initially allocated currently used ---------------------------------------------------------------------------Semaphore 2048 1 ---------------------------------------------------------------------------Region 256 0 ---------------------------------------------------------------------------Mailbox 256 3 ---------------------------------------------------------------------------Fork/Join ---------------------------------------------------------------------------Type No. threads No. threads No. threads Max. No. threads created finished remaining per instant ---------------------------------------------------------------------------Fork/Join 2 1 1 2 ---------------------------------------------------------------------------Classes ---------------------------------------------------------------------------Class Name #object #object #object #memory % allocated freed notfreed total,static ---------------------------------------------------------------------------MClass_A 1 0 1 0.02,0.00 ----------------------------------------------------------------------------

Testbench Optimization 10-12

header 1 0 1 0.01,0.00 ---------------------------------------------------------------------------packet 1 0 1 0.01,0.00 ---------------------------------------------------------------------------MClass_B 1 1 0 0.01,0.00 ---------------------------------------------------------------------------Dynamic Array Statistics Class Name: MClass_A No. of objects: 1 Array Name Array Type Data Type #elements -----------------------------------------------------------a_q smart queue integer 4 a_dyn dynamic array packet 10 a_assoc associative array header 3 -----------------------------------------------------------Class Name: header No. of objects: 1 Array Name Array Type Data Type #elements ----------------------------------------------------------------------------------------------------------------------Class Name: packet No. of objects: 1 Array Name Array Type Data Type #elements ----------------------------------------------------------------------------------------------------------------------Class Name: MClass_B No. of objects: 0 Array Name Array Type Data Type #elements -----------------------------------------------------------b_assoc associative array header 0 ------------------------------------------------------------

-------------------------------------------------------------------------Total Classes : 4 -----------------------------------------------------------------------------

Testbench Optimization 10-13

Global Dynamic Array Types --------------------------------------------------------Array Name Array Type Data Type #elements ----------------------------------------------------------------------------------------------------------------Mailboxes -------------------------------------------------------Mailbox ID #messages -------------------------------------------------------Mailbox[1] 4 Mailbox[3] 3 --------------------------------------------------------

The log file shown in Example 10-4 indicates that: 1 semaphore and 3 mailboxes were used in the simulation. 2 threads were created and 1 thread was incomplete at the end of the simulation. The maximum number of threads running at any given instance of simulation time was 2. A MClass_A object, a header object and a Packet object were not freed but, a MClass_B object was freed at the end of the simulation. Dynamic array statistics gives the details of the smart queues, dynamic arrays and associative arrays created for each of the different class objects. Mailboxes gives the mailbox IDs created and the number of constituent elements created during the simulation.

Testbench Optimization 10-14

Memory Profiling Analysis


Incomplete threads indicate potential problems in the testbench implementation. The user should determine, however, whether or not this is the desired behavior. Memory allocated for an OpenVera object can be freed and reused. The profiling results can be used to optimize the memory usage in the following ways: A continuous increase in the number of created objects indicates a problem with objects not being freed. In the above example, 11,167 packets were created. Only 11,000 objects were freed by the end of the simulation. This may indicate that the testbench does not discard packets after the packets are processed. There is a potential that longer simulations would exhaust memory. Handles that reference unused objects should either be set to null or reused for creating new objects in which case the handles automatically de-reference the old and then reference the new object.

Using vera_profile_object_verbose
When this option is used, the class name, the number of objects of this class that have been newed and freed, and the stack trace of the location at which the objects were newed are reported for each location of unfreed objects. In addition, the total number of handles referencing these objects is recorded. Information reported in the memory profiler table for each location is listed below. the class name

Testbench Optimization 10-15

the number of objects of this class that have been newed and not freed the stack trace of the location the total number of handles referencing these objects

An object will be automatically garbage collected when there are no further references to that object. Typical conditions for un-garbage collected objects are: The object is part of a doubly-linked list. The object is part of a circular list. The object's class contains a method that forks off a thread, and the thread is still running.

Verbose Profile Example


The following example explains the output report generated by the memory profiler with vera_profile_object_verbose. The OpenVera source file (test.vr) defines two classes, C and B and a task mytask(). mytask() created (newed) three objects of class C, Obj1, Obj2 and Obj3. Two of the three objects are freed at the end of the task. Two object handles of class C, handle1 and handle2, are created with reference to obj1. mytask() also created (newed) an array of objects of class B.

Testbench Optimization 10-16

Example 10-5 test.vr


class C { integer myvar; } class B { integer myvar; } task mytask() { Obj1 = new(); Obj2 = new(); Obj3 = new(); for (i=0; i < 5; i++) { Obj[i] = new(); } Hand1 = Obj1; Hand2 = Obj1; Obj1 Obj2 } = null; = null;

program mytest { integer i; C Obj1 , Obj2 , Obj3; C Hand1 , Hand2; B Obj[5]; mytask(); }

Run command:
vera -cmp test.vr vera_cs test.vro +vera_profile_object_verbose

Testbench Optimization 10-17

The un-freed object trace table is shown in Example 10-6.

Example 10-6 Unfreed Object Trace Table


============================================================ Unfreed Object Trace ============================================================ Class name: B (5 objects) New'ed at: task mytask [test.vr : 14] program mytest [test.vr : 30] Total number of handles referencing these objects: 5 -----------------------------------------------------------Class name: C (1 object) New'ed at: task mytask [test.vr : 11] program mytest [test.vr : 30] Total number of handles referencing this object: 1 ---------------------------------------------------------Class name: C (1 object) New'ed at: task mytask [test.vr : 9] program mytest [test.vr : 30] Total number of handles referencing this object: 2 ----------------------------------------------------------

The first table entry shows that all five class B objects are not freed. Since none of these objects have been nulled, all object handles created with new() still exist. The second table entry shows that one class C object (Obj3) is unfreed and is reference by one object handle. In this case, the handle was created when the object was newed. The third table entry shows that one class C object (Obj1) is unfreed and is referenced by two object handles (Hand1, Hand2). Since Obj1 has been nulled, the object handle created by new() no longer exists.

Testbench Optimization 10-18

Obj2 has been nulled and has no object handles referencing it. Therefore, it has been freed and does not show in the table.

Save and Restart


Vera running with VCS provides a save and restart feature that allows checkpoints of the simulation to be saved at arbitrary times. The resulting checkpoint files can be executed at a later time, causing simulation to resume at the point immediately following the save Benefits of save and restart include: Regular checkpoints for interactively debugging problems found during long batch runs Executes common simulation system tasks such as $reset just once in a regression

Linking Vera with VCSs Save/Restart


The following is a brief overview of how to link Vera into VCS for use with VCS's save/restart capability. This note assumes some familiarity with the VCS environment. For more detailed information on save/restart, please refer to the VCS documentation. To generate a "simv" with Vera, you need to invoke "vcs" with your verilog model(s) using the correct Vera compile time switch. For example: -vera:
vcs -vera -f vcs_user_options

Testbench Optimization 10-19

The -vera switch is used when all HDL signals are bound statically to the Vera interface. -vera_dbind:
vcs -vera_dbind -f vcs_user_options

The -vera_dbind switch is used if any HDL signals are dynamically bound. Note: Dynamic linking using the libSysSciTaskPIC.a library is not supported After creating simv, run:
simv +vera_load=compiled_vera_file.vro

Once simv executes a save task, such as $save("savef"), you can use the save file (that is, savef) to restore the combined VCS and Vera environments to the state they had at the time the save was executed. The restore can be achieved by executing the following command:
simv -r savef

or simply execute the save file itself:


savef

Different arguments can be passed to a saved Vera/VCS run by passing user-defined Vera plus arguments into each run. For example, in the linking example above, one may execute:
simv -r savef +vera_run=1

or
Testbench Optimization 10-20

simv -r savef +vera_run=2

and call Vera's $get_plus_arg(NUM, "vera_run") within your Vera code to obtain the value of the given "vera_run=2", thus allowing a single Vera program to do different things after a restart. See:
$VERA_HOME/examples/vug_examples/ch21_tb_optimization

Setting the environment variable, VERA_OVERWRITE, allows you to overwrite any open files being written to by the restart. Vera may control the calls to the VCS save feature through the use of Veras hdl_task feature. In this model, the save call is contained in a Verilog task that Vera calls to save the simulation.

Restrictions
There are some things that will not work across a saved Vera simulation: VSV Because Vera is unable to restart the remote processes used during VSV, a system verification that includes connections to master or slave processes cannot be restarted. A fatal error message will result. ISDB An ISDB database will not remain open across save/restarts. An ISDB database left open at the time of the save will appear to be closed at the time of the restart. In order to dump more information, a new database needs to be created. The signals and variables to be recorded in the database have to be specified after the restart.

Testbench Optimization 10-21

Debugger The Vera debugger will not remain open across a save/restart. That is, if the Vera debugger window is active at the time of the save, it will not be active upon a restart. To bring up the debugger window, you must do so manually. The Vera get_plus_arg option may be used to specifically select the debugger when the simulation is restarted by specifying this plus argument in the command line. For example:
restore_test +arg_check="start_debugger_GUI"

DirectC and UDF If your testbench includes DirectC or UDF routines that do file I/O, the routines must detect both the save and restart events, closing and reopening files as needed. Right before calling a Verilog task, which in turn calls $save, call a DirectC or UDF routine which closes all files. Right after calling the Verilog task, call a DirectC or UDF routine which reopens all files. Plus Arguments If your testbench uses plus arguments, you must add code to process the plus arguments after restart. Therefore, right after calling the Verilog task, which in turn calls $save, the code should process any plus arguments. Files All open files that were opened via fopen prior to the save, will be restored to the state they were in at the time of the save. If a previously open file can no longer be opened, it will result in a fatal error.

Testbench Optimization 10-22

Example 10-7
save_task.v module SaveTask ; task save_sim ; begin $save("restore_test") ; end endtask endmodule

Example 10-8
#include <vera_defines.vrh> #include "clk_gen.if.vrh" // HDL task declaration hdl_task save_task() "SaveTask.save_sim" ; program test { integer arg_check1 ; string arg_check0 ; string save_arg_check0 ; repeat(50) @(posedge CLOCK) ; save_task(); // Advance test cycles repeat(100) @(posedge CLOCK) ; // start debugger after restart if plus arg is set if( get_plus_arg(CHECK, "arg_check=")) { arg_check0.bittostr(get_plus_arg(STR, "arg_check=")) ; if (arg_check0 == "start_debugger_GUI"){ breakpoint ; } } // end program test

Example 10-9
vcs clock_gen.v test.vshell clk_gen.test_top.v save_task.v -vera simv +vera_load=test.vro restore_test +arg_check="start_debugger_GUI"

Testbench Optimization 10-23

Dynamic Loading of Vera Object Files


In pre-5.2 versions of the Vera flow, a complete program is loaded at the start of simulation. This program resides in the memory until the simulation ends. In Vera v5.2, compiled Vera files (.vro files) can be dynamically loaded and unloaded into a running Vera program. This facility is under control of the Vera program. This capability facilitates: modeling a test environment in which a large set of tests can run under a common global environment, bringing the amount of memory needed to hold a large set of tests under the users control, managing a large set of scenarios, which may consist of many combinations of simple tests, by controlling the name-space directly from within the Vera program.

The four main components of this capability are: The Vera Dynamic Executable Object (VDEO) VDEO Loading VDEO Unloading Execution of VDEO

Creating a Vera Dynamic Executable Object (VDEO)


A Vera Dynamic executable object or VDEO is a compiled Vera file that can be dynamically loaded, unloaded and executed at runtime.

Testbench Optimization 10-24

Any Vera source file can be made into a VDEO by doing the following: 1. Include the file, VeraDyn.vrh, which is predefined in $VERA_HOME/include. For example:
#include <VeraDyn.vrh>

2. Provide a class derived from the in-built base class VRO or its sub class defined in the main program. For example:
class DynTest extends VRO { virtual task execute(); virtual task cleanup(); task new(); } The in-built class VRO has the following form: class VRO { virtual task execute(); // entry point to subprogram virtual task cleanup(); // wrap up before unloading }

3. Provide an implementation for the execute() and cleanup() methods of the derived class. For example:
DynTest::execute() { /* code to run the program */ } DynTest::cleanup() { /* cleanup code prior to unloading */ }

4. Compile the Vera file into a VDEO using a special compiler switch -dyn. For example, the following will produce a dynamic.vro file, which can then be loaded at run-time using the vLoad() system call:
vera -cmp -dyn dynamic.vr

Compiler switch dyn is used to ensure that the VDEO has a unique entry point defined.

Testbench Optimization 10-25

5. Run the Vera main program using a special run-time switch +vera_dyn if there is an intent to dynamically load a VDEO at run-time.
vera_cs +vera_dyn main.vro

Loading and Unloading a VDEO File Loading


The vLoad() system call loads a VDEO file into a running Vera program. The syntax for vload() function is:
function VRO vLoad(string vro_file);

where vro_file is the pathname of the .vro file to be loaded. A successful call to vLoad() causes the corresponding .vro file to be loaded into the address space of the calling program. References to global variables in the VDEO are bound to the global variables in the calling program. If the VDEO contains references to global variables that are not defined in the calling program, the call to vLoad() fails. Once the indicated VDEO has been successfully loaded, vLoad() locates the VRO sub-class (that is, the class derived from the VRO base class), creates an instance of that class, and returns a handle to the corresponding base class. vLoad() returns a handle to the newly loaded subprogram. If the call fails, vLoad() returns null. A call to vLoad() will fail if the indicated vro-file cannot be found, cannot be read, is not a VDEO, or a symbol is left unresolved.

Testbench Optimization 10-26

Unloading
Use the following system call to unload the VDEO:
task vUnloadAll()

The vUnloadAll() task disassociates all currently loaded VDEOs from the calling Vera program. Once a VDEO is unloaded, its symbols and executable code are no longer available. The vUnloadAll() call performs the following actions for each VDEO, in this order 1. Calls the cleanup() method of the given VRO It is the responsibility of each VDEO to cleanup any object that may contain references to symbols or code local to the VDEO. This includes objects with virtual methods in the VDEOs address space, threads forked off from within the VDEOs, and random constraints involving global variables and VDEO local classes. The cleanup() method should also close all open files, and shutdown any DirectC or UDF code. 2. Checks to ensure that no threads forked from within the VDEO remain. For each such thread, a fatal error message is issued. 3. Removes all data local to the VDEO from the address space. 4. Reclaims all local VDEO memory, including symbol information and executable code. A successful call to vUnloadAll() removes all the VDEOs from the address space of the calling program. Attempts to references symbols or execute code local to a VDEO will result in a fatal exception (for threads or virtual methods), or undefined results (for random constraints or other heap-allocated objects).
Testbench Optimization 10-27

Objects shared between the main program and the VDEO will not be garbage-collected when vUnloadAll() is called; the main program will have to de reference them before they are garbage-collected. Unloading does not automatically remove objects. Global and local object references in the subprogram must be cleared before they can be unloaded. Unloading does not automatically remove mailboxes, regions and semaphores allocated by the subprogram.

Execution
A VDEO can be executed by calling its execute task, for example:
VRO hVro = vLoad("dynamic.vro"); hVro.execute();

Example 10-10 main.vr


#include <VeraDyn.vrh> interface ifc{ input [7:0] inp; output [7:0] outp; } // function called by test function integer check_inp(){ check_inp = (ifc.inp == 128) ? 1 : 0; } program main{ integer count = 0; // variable used by test VRO hDynTest = vLoad ("test1.vro"); }

Testbench Optimization 10-28

Example 10-11 test1.vr


#include <VeraDyn.vrh> // Imports from Main Program extern function check_inp(); extern integer count; class TestObject{ string name; task new(string _name) {name = _name;} } class DynTest extends VRO{ TestObject obj; virtual task execute(); virtual task cleanup(); task new() {obj = new( "DynTest" );} } task DynTest::execute() { integer i, j = 0; for( i = 0; i < 5; i++ ){ @(posedge CLOCK); // Reference external function j += check_inp(); } // Reference external variable count += j; } task DynTest::cleanup(){ obj = null;

Limitations
All global variables, interfaces, ports and binds must be declared and defined in the main program, that is, the program loaded at the start of the simulation using Vera's conventional program loading mechanism

Testbench Optimization 10-29

The main program must be self-contained, that is, it may not contain unresolved references to either variables or functions defined in a VDEO. A VDEO may not contain global definitions, either variables, ports, binds or interfaces. However, extern global declarations are allowed. A VDEO may only contain unresolved references to global variables, functions, tasks, ports, binds or interfaces that are defined in the main program. Tasks or functions cannot be exported from a VDEO to either the main program, or to other VDEOs. However, virtual methods of a VDEO can be executed from the main program. VSV calls are not supported in a VDEO Vera Debugger will not support a VDEO

Testbench Optimization 10-30

11
Vera Interactive Debugger 11
The Vera graphical debugger is a valuable debugging and testbench analysis tool. Its windowed interface allows easy configurability, simplifying use. Its monitoring mechanisms grant access to variables, signals, and expressions resulting in quick and simple testbench analysis. This section shows how to launch, navigate and use the debugger features. Debugger Overview How Debugging Works Menus Toolbar Buttons Project Workspace Window Source Window Local Watch Window

Vera Interactive Debugger 11-1

Global Watch Window Debugging with Breakpoints Stepping Vera Code Watching Variables and Expressions Forcing a Value Finding a String in Source Preferences and Fonts

Compiling Vera Source Code for Debugging When compiling OpenVera source code to be used with the Vera debugger (see The Vera Testbench Flow on page 2-2), use the -g compiler switch:
vera -cmp -g filename.vr

If you do not specify the -g switch, debugger information is not stored in the compiled object files. This effectively disables the local watch window. Unless the compiled object files are not going to be debugged, you should always use the -g switch. Note: Vera object files compiled with the -g switch are slightly larger than those compiled without the switch. Launching the Debugger One or more of the following options will bring up the debugger. The vera_debug_on_start runtime option (see vera_debug_on_start on page 3-30): The debugger is accessed at the start of the main Vera program.

Vera Interactive Debugger 11-2

The vera_debug_on_errror runtime option (see vera_debug_on_error on page 3-30): Invokes the debugger when a verification error is encountered. The vera_debug_on_int runtime option (see vera_debug_on_int on page 3-30): When the simulation is running, the debugger will start after you press Ctrl-C When using VCS, the simulation command $vera_debugger; is issued from the cli prompt. A Vera breakpoint statement is reached.

Once the Vera debugger comes up, online help is available through what is called, Whats This. Simply click on the Whats This command, drag the ? (question mark) over the window or command for which you are seeking help, and drop the ? by releasing the mouse button. A dialog box will automatically be displayed, giving help text for that window or command.

Debugger Overview
This section includes a brief overview of the Vera debugger, including terminology used throughout this section.

Vera Interactive Debugger 11-3

Figure 11-1
Menu Bar Toolbar Buttons

Project Workspace

Source Window

Local Watch Window

Global Watch Window

Status Bar

Debugger Main Components


Menu Bar Toolbar Buttons Project Workspace Source Window Local Watch Window Contains drop-down menu items to drive and configure the debugger. These buttons correspond to frequently used menu items. A tabbed pane that shows either Breakpoints, Call Stack, Files, or Inter Thread Communication (ITCs). Displays Vera source code for the current frame. Displays all variables and objects with current values, local to the current frame.

Vera Interactive Debugger 11-4

Global Watch Window

A tabbed pane that allows you to watch user-defined expressions, variables and objects, regardless of the current frame. You are given 3 Watch tabs to organize your views. The Meta Watch tab allows you to watch interesting mailboxes, regions and semaphores. Displays the current debugger status, file and line number in addition to the Simulation Time.

Status Bar

Context Menus The debugger provides context menus as a quick access to relevant commands for a particular window or selection in a window. These pop-up via right mouse click in a window. Whats This On-line Help Online documentation is available through the Whats This cursor. Click the Whats This toolbar button:

or select Help-Whats This. Your cursor will turn into an arrow with question mark. Documentation will pop-up in a tool tip for the next thing you click on. This can be menu items, toolbar buttons, windows and tabs. Click the tool tip to exit the Whats This mode and close the tool tip. Dockable Windows The Vera debugger allows you to configure the display of its windowpanes. Docked windows are attached to the main window frame at the docking bar:

Vera Interactive Debugger 11-5

To move them within the main Debugger window, grab the docking bar and drag the window. It will attach to the edges of the main window where it was dropped. Docked windows can be made floating, so you can tile or cascade them via the Windows menu. Floating windows have title bars that allow you to minimize, maximize and close them:

Docked windows can be pulled out of them main Debugger window by grabbing the docking bar and dragging it beyond the frame, or edge, of the main Debugger window. To return it to the main Debugger window, drag it back inside the frame. Change window size by grabbing the edge of the window and dragging it.

How Debugging Works


The debugger is designed to debug all Vera programs running in a particular HDL simulation. Each Vera program runs one or more concurrent processes, known as threads. The root or top-level thread for each program is defined by the execution of that program's program block. Child threads are created by fork-join statements. Each thread has a call stack, known as "stack," consisting of one or more stack frames, which are referred to simply as "frames". Each time a thread performs a task or function call, information about the call is generated and saved on the thread's stack in a frame.

Vera Interactive Debugger 11-6

Debugging is centered around the "current/selected" stack frame shown in the Call Stack View on page 11-17. This frame defines the context for the local variables in the Local Watch Window on page 11-22 and the context for evaluating the expressions in the Global Watch Window on page 11-24. The "current" frame may be changed by: 1. Selecting another frame in the Call Stack window. 2. Using the controls in the Local Watch window to navigating up and down the stack containing the current frame. 3. Using the context menu in the ITC and Meta Watch windows to attach to a different thread. Attaching to a thread automatically selects the leaf frame of that thread. 4. Advancing the simulation. When the simulation advances, the frame where the simulation halted is automatically made current. Multiple main windows The debugger supports multiple main windows with independent views into the simulation (see Figure 11-1). By default, all main windows track the same current frame. When the current frame is changed in one main window, all others will select the same frame. As an option, a main window may be locked so that it tracks its own independent current frame (see Windows Menu on page 11-12). The current frame in a locked window may be changed, but it will not affect the current frame in other windows. Similarly, the current frame in other windows may be changed, but it will not affect the current frame in a locked window.

Vera Interactive Debugger 11-7

When a window is locked, advancing the simulation does not automatically select the frame where the simulation halts. The window's current frame remains unchanged.

Menus
The Vera debugger menu items become sensitive when the command is available based on the current window or selection. Otherwise, they are disabled. File Menu

Open File Close File Quit

Opens the specified file in the source window. Closes the file displayed in the active source window. Exits the debugger and ends the simulation, if running.

Edit Menu

Find ... FindNext FindPrev

Finds a specified text string in the active window. Finds next occurrence of specified text string in the active window. Finds next occurrence of specified text string in the active window.

Vera Interactive Debugger 11-8

View Menu

File Toolbar Edit Toolbar Debug Toolbar Windows Toolbar Local Watch Window Global Watch Window Log Window Project Window Line Up

Toggles display of the File Toolbar buttons. Toggles display of the Edit Toolbar buttons. Toggles display of the Debug Toolbar buttons. Toggles display of the Windows Toolbar buttons Toggles display of the Local Watch window. Toggles display of the Global Watch window. Toggles display of the simulation Log Window Toggles display of the Project Workspace window. Lines up docked windows as compactly as possible

Vera Interactive Debugger 11-9

Debug Menu

Step

Steps into the next executable statement in the Vera program. This command will step into functions/tasks, but it may change threads. Use Step (In Thread) to step within a thread. Single steps the current Vera thread by one line. This command will not step into functions/tasks. Continues the simulation. This command will advance Vera to the next breakpoint. Runs simulation to the current cursor location in the source window. Steps out of a function or task. Single step within the same thread. This will advance the current Vera thread by one line and will step into functions/ tasks.

Next Continue Run To Step Out Step (In Thread)

Vera Interactive Debugger 11-10

Step (Universal)

Single step within any program. This command is not bound to a thread or program. Therefore, Vera may stop in another thread or program. This will step into functions/tasks. Creates an enabled breakpoint at the current selected line. Creates an enabled breakpoint at the first line of a task or function. Class methods can be referenced (for example, class_name:: method_name). Halts simulation when the cycle count changes for a particular interface clock. Halts simulation when the value of a user defined expression changes. Adds the variable, expression, or object selected in the active source window to the global watch window. Forces a variable value in the current context. Enables a disabled debugger breakpoint at the current cursor line. Disables an enabled debugger breakpoint at the current cursor line. Deletes a debugger breakpoint at the current cursor line. Halts the Vera simulation and returns control back the Vera debugger. Halts simulation and gives control to the HDL simulator. Return control to Vera by continuing simulation from the simulator.

Add File/Line BP... Add Instance BP...

Add Cycle BP ... Add Expression BP ... Add Watch Set Value ... Enable BP Disable BP Delete BP Stop in Vera Stop in Hdl

Note: The following is applicable to any action that advances the simulation. If an intervening breakpoint is encountered, the simulation halts.

Vera Interactive Debugger 11-11

Options Menu

Preference Fonts ...

Configures debugger settings based on user preferences Allows user to specify debugger fonts

Windows Menu

New Debug Window Close Debug Window Lock Debug Window Cascade Tile Tile Horizontally Quick Window Access

Opens a new main debugger window. Closes the current main debugger window. Locks the main debugger window to the current thread in the Call Stack window. Cascades all floating Source windows in the main window Tiles all floating Source windows in the main window Tiles all floating Source windows horizontally in the main window Pops forward currently open Source windows in your session.

Vera Interactive Debugger 11-12

Help Menu

Content About Whats This

Opens this document in a Web browser Displays current debugger revision number and simulator command line arguments. Accesses on-line documentation for the next thing you click.

Toolbar Buttons
The Vera debugger provides toolbar buttons for commonly used commands. Refer to the Menus on page 11-8 for a description of each.

Project Workspace Window


The project workspace is made up of tabbed views. These display the loaded Vera files in the Files tab, the current breakpoints with status in the Breakpoints tab, the inter-thread communication including mailboxes, regions and semaphores in the ITCs tab, and the call stack in the Call Stack tab.

Vera Interactive Debugger 11-13

Files view This tab is for viewing the source files used to build the .vro files currently used by Vera.

Source filename

Program name

Sortable Column

Note: If there are multiple programs, the source files are organized by program name.
If you want to: Expand the tree Collapse the tree Display Source Find a file Do this: Left click the + icon. Left click the - icon. Left click a .vr filename. The source file will be opened in a Source window. Right click to open the context menu and select the "Find..." item

Breakpoints View This tab is used for viewing, enabling, disabling and deleting the current breakpoints. When a breakpoint stops the simulation, it will be displayed in red. This view uses a context menu available via right mouse click.

Vera Interactive Debugger 11-14

Breakpoints listed with description and type Status of Breakpoint

If you want to: Show Source

Do this: Left click on a file/line breakpoint to display that line in a source window. The line and number will be highlighted in blue in a Source window. Right click on a breakpoint and select Enable from the context menu. Right click on a breakpoint and select Disable from the context menu. Right click on a breakpoint and select Delete from the context menu. Right click on a breakpoint and select Enable All from the context menu. Right click on a breakpoint and select Disable All from the context menu. Right click on a breakpoint and select Delete All from the context menu. Right click to open the context menu and select the "Find..." item.

Enable a breakpoint Disable a breakpoint Delete a breakpoint Enable all breakpoints Disable all breakpoints Delete all breakpoints Find text

Vera Interactive Debugger 11-15

ITCs View This tab is used for viewing inter-thread communication primitives: mailboxes, regions and semaphores. Here you can see the internal data for the primitive and the list of waiting threads. This view uses a context menu available via right mouse click. This view may contain a large number of items; furthermore, the items may be dynamic, as they can be created or destroyed every time the simulation advances. Therefore, it is generally easier to monitor items of interest by adding them to the Meta Watch view in the Global Watch Window.
Waiting Threads

ITC primitives

Internal Data

If you want to: Expand the tree

Do this: Left click the + icon or double click the item to expand.

Vera Interactive Debugger 11-16

Collapse the tree Watch an ITC item of interest Attach to a thread Find text

Left click the -icon or double click the item to expand. Right click on the item of interest and select Add Meta Watch from the context menu. Right click on a frame and select Attach Thread from the context menu. Right click to open the context menu and select the "Find..." item.

Call Stack View This tab is used for viewing the status of various threads and stack frames running in Vera. This view is cross-linked with the Source and Local Watch windows via left clicking on objects. This view uses a context menu available via right mouse click.

Threads running Paths to activebreakoint and current frames overlap

Status

Stack Frames

Vera Interactive Debugger 11-17

This view utilizes color-coded text to show you the current and active-breakpoint threads and stack frames.
Highlight Color Red Blue Purple Meaning Current thread and stack frame. Active-breakpoint thread and stack frame. Current and active-breakpoint thread and stack frame.

The status column will display one of the following:


READY CALL WAIT_ON_SEM WAIT_ON_REG WAIT_ON_MBOX WAIT_ON_EXPECT WAIT_ON_DRIVE WAIT_ON_SAMPLE WAIT_ON_SYNC WAIT_ON_FORK The thread is executing. The corresponding code has called a function. The thread is waiting on a semaphore_get. The thread is waiting on a region_enter. The thread is waiting on a mailbox_get. The thread is waiting due to an expect. The thread is waiting due to a blocking drive. The thread is waiting due to a blocking sample. The thread is waiting for an HDL signal sync. The thread is waiting for child threads to complete. The thread is waiting for event vars to trigger. The thread is waiting due to an HDL task call. The thread is waiting due to a wait_var(). The thread is waiting due to a VSV call. The thread is waiting due to a wait_child().

WAIT_ON_EVENT WAIT_ON_HDL WAIT_ON_VAR WAIT_ON_VSV WAIT_ON_CHILD

Vera Interactive Debugger 11-18

WAIT_ON_ZOMBIE

The thread is waiting for all child threads to complete.

If you want to: Expand the tree Collapse the tree Watch stack frame or thread Display Source

Do this: Left click the + icon. Left click the - icon. Right click on the item of interest and select Add Meta Watch from the context menu. Right click on a frame and select Go to Definition from the context menu, or left click in the Instance column of the frame. If that file is already open, the Source window displaying that file will be popped forward, otherwise a new Source window will be opened. Right click on a task/function and select Add Instance BP from the context menu. Left click the Instance column for the frame. The local variables will be displayed in the Local Watch window. Right click to open the context menu and select the "Find..." item.

Break on an instance See local variables Find text

Display Limits The default depth of a call stack is 100. This is configurable via Preferences... Cross-link to Watches and Source Window Selecting a frame in the Call Stack will automatically display variables for that frame in the Local Watch window and re-evaluate the items in the Global Watches. It will also automatically highlight the current line in that frame in a Source window.

Vera Interactive Debugger 11-19

Source Window
This window shows Vera source code, line numbers and current line. Here, you can set breakpoints, enable, disable and delete line breakpoints. This is a read-only window since the source code must be consistent with the debug information within Vera. This window uses context menus via right mouse click.

Current line to execute Selected text Breakpoint set and enabled Source cursor highlights line

Breakpoint set and disabled

If you want to: Select text View a file

Do this: Left click at the start of the text, drag to the end of the text and let go. Left click a file from the Files tab in the Project Workspace window

Vera Interactive Debugger 11-20

Set a line breakpoint

On a line without a breakpoint, right click on the source at the line you want to break on and select Add File/Line BP from the context menu. To create a line breakpoint without going through a dialog, left click in the line number column. On a line with a disabled breakpoint, right click on the source at the line you want to enable and select Enable BP from the context menu. On a line with an enabled breakpoint, right click on the source at the line you want to disable and select Disable BP from the context menu. Right click on the source at the line you want to run to and select Run To from the context menu. Or, left click on the line to move the source cursor to that line and select Debug-Run To from the menu. Select text in the source window, right click and select Add Expression BP from the context menu. Select text in the source window, right click and select Add Instance BP from the context menu. Select text in the source window, right click and select Add Cycle BP from the context menu. Select text in the source window, right click and select Add Watch from the context menu. The watch will be added to the active Watch view in the Global Watch window. Select a variable in the source window, right click and select Set Value from the context menu. If you have more than one Source window open, click in the Source window to search. From the menus, select Edit-Find Right click to open the context menu and select the "Goto..." item. See Preferences

Enable a line breakpoint

Disable a line breakpoint

Run to a specific line

Set an expression breakpoint Set an instance breakpoint Set a cycle breakpoint Watch a variable/ expression

Force a value Find a string in the file

Go to a Line Change the tab width

Vera Interactive Debugger 11-21

Local Watch Window


The local watch window allows you to watch all Vera variables that are local to the current frame. These variables are block- and class-scoped. Class-scoped variables are grouped hierarchically under a this item in the watch window. The Context field in this window is cross-linked with the Call Stack in the Project Workspace and with the Source window. This view uses a context menu available via right mouse click.

Current frame in call stack

Buttons to navigate the call stack Variables and values in the current frame Select frames in the call stack using this drop-down list.

If you want to: Select a variable Watch a variable regardless of the current frame Change radix

Do this: Left click on the variable. Only one variable can be selected at a time. Select the Watch tab in the Global Watch window that you want the variable added to, right click on the variable and select Add Global Watch from the context menu. Right click on the variable or expression and select the radix from the Set Radix menu. Can be one of Binary, Octal, Decimal, Hexadecimal or String. This applies to the Local Watch window only. To change defaults, see Preferences.

Vera Interactive Debugger 11-22

Force a value

Right click on the variable and select Set Value from the context menu. This value will remain until it is overwritten by the code or another value is forced. Change number of displayed array elements. Right click on an array variable and select Set Range... Right click on a variable or object and select Set Expression BP from the context menu. The new breakpoint will be added to the Breakpoints tab, enabled. Click the Context drop-down icon and select the frame you want to view. Click the Up One Frame button in the Local Watch window. Click the Down One Frame button in the Local Watch window. Left-click the + icon to the left of the array. Left-click the - icon to the left of the array. Right click to open the context menu and select the "Find..." item

Set Range...

Break on variable change

View variables from another frame in the call stack Move up the call stack Move down the call stack Expand an array variable or object instance Collapse an array variable or object instance Find text

The local watch window will update the variables if you: Change the current frame. Advance the simulation.

Display Limits Both Array and Object variables are expandable and collapsible to see their components. The number of array entries is limited to 50 by default, and is configurable in Options-Preferences. The number of object members is unlimited.

Vera Interactive Debugger 11-23

Cross-link to Call Stack and Source Window The Context field and the Call Stack are always synchronized. When you change the current frame in the Context field, the Call Stack will select it as the current frame. Changing the Context field will display the current line and frame in a Source window, highlighting current line number in blue.

Global Watch Window


The global watch window is made up of tabbed views. Three are watch windows, labelled Watch 1 through Watch 3. Here, variables and expressions of interest can be monitored regardless of the current context, and variables may be forced to a user specified value. Watch windows always contain one blank entry in the tree structure for entering expressions with the keyboard. The last tab is the Meta Watch tab, which displays stack frames and inter-thread communication primitives of interest from the ITC or Call Stack tabs in the Project Workspace window. Watch Views 1 through 3

Variable

Variable values

Expression

Blank entry for adding expressions

If you want to:

Do this:

Vera Interactive Debugger 11-24

Select a variable Watch a variable

Left click on the variable. Only one variable can be selected at a time. Select the Watch tab you want the variable added to, then add a global watch from the Source or Local Watch window. Right click on the variable or expression and select the radix from the Set Radix menu. Can be one of Binary, Octal, Decimal, Hexadecimal or String. This applies to the current tab only. To change defaults, see Preferences. Change number of displayed array elements. Right click on an array variable and select Set Range... Right click on the variable, object, or expression and select Set Value from the context menu. This value will remain until it is overwritten by the code or another value is forced. Right click on a variable or object and select Set Expression BP from the context menu. The new breakpoint will be added to the Breakpoints tab, enabled. Right click on a variable, expression or object and select Delete from the context menu. Select the blank entry. Press F2 to get into edit mode. Type the expression and hit enter. The expression and value are now visible in the Watch tab and a new blank line is added. Right click to open the context menu and select the "Find..." item.

Change radix

Set Range...

Force a value

Break on variable change

Delete Type in an expression

Find text

Meta Watch View Use this view to monitor meta objects like programs, threads and ITC primitives of interest. Vera will not automatically break on changes for these. This view uses a context menu available via right mouse click.

Vera Interactive Debugger 11-25

If you want to: Select a variable Expand the tree Collapse the tree Watch a thread or frame Watch an ITC primitive Watch an event variable Attach to thread Delete Find text

Do this: Left click on the variable. Only one variable can be selected at a time. Left click the + icon or double click the item to expand. Left click the - icon or double click the item to expand. Add a Meta watch from the ITCs or Call Stack tab in the Project Workspace window. Add a Meta watch from the ITCs window Add a Meta watch from the Local or Global watch windows that lists the event variable. Right click on a frame and select Attach Thread from the context menu. Right click on an item and select Delete from the context menu. Right click to open the context menu and select the "Find..." item.

Debugging with Breakpoints


The Vera debugger allows you to set various kinds of breakpoints to help you debug your testbench. They are: File/Line Breakpoints, Expression Breakpoints, Instance Breakpoints, and Cycle

Vera Interactive Debugger 11-26

Breakpoints. File/Line and Instance breakpoints allow an optional Boolean expression that will cause Vera to stop on that breakpoint only if the expression evaluates to true. For all dialogs, edit any fields, and click Accept to send the breakpoint to Vera. If Vera accepts the breakpoint as valid, the breakpoint will be added to the Breakpoints tab in the Project Window and if a file/line breakpoint, it will be denoted in the Source window. Otherwise, an error pops up to explain why it was not valid. Clicking Cancel discards any changes in this dialog and closes it. File/Line Breakpoints File/Line breakpoints stop Vera at a Vera file and line number. Selecting Add File/Line BP brings up the following dialog. When selected from the context menu in the Source window, it will populate the fields with the file and line you right clicked on. When selected from the Debug menu or toolbar, it will populate with the line that has selected text, or if nothing is selected, the Source window cursor line.

Vera Interactive Debugger 11-27

Expression Breakpoints Expression breakpoints will stop Vera on value changes of the expression. If a variable referenced in the expression goes out of scope, the breakpoint may never trigger. Selecting Add Expression BP brings up the following dialog. When selected from the context menu in the Source window, it will populate the fields with the selected text in the Source window. It is unavailable via context menu when nothing is selected in the Source window. When selected from the context menus in the Local or Global Watch windows, it will just add an expression breakpoint for the variable you right clicked on. When selected from the Debug menu or toolbar, it will open with a blank field.

Vera Interactive Debugger 11-28

Instance Breakpoints Instance breakpoints will stop Vera at the first line of a task or function. Selecting Add Instance BP brings up the following dialog. When selected from the context menu in the Source window, it will populate the fields with the selected text in the Source window. It is unavailable via context menu when nothing is selected in the Source window. When selected from the context menus in the Call Stack tab of the Project Workspace window, it will populate with the instance name of the frame you right clicked on. When selected from the Debug menu or toolbar, it will populate with the selected text in the Source window, or if nothing is selected, it will open empty. When editing the fields: The task or function name is required. When specifying a method outside the current scope, use the syntax class::method.

Vera Interactive Debugger 11-29

Expression field is optional and has no default value. The scope of the variables within the expression can be global, class or task arguments. Variables local to the task cannot be part of the expression.

Cycle Breakpoints Cycle breakpoints are automatically reset after they are triggered. This means if Cycles to Wait is set to 2, Vera will break every other cycle of the specified interface. Selecting Add Cycle BP brings up the following dialog. When selected from the context menu in the Source window, it will populate the Interface Name field with the selected text in the Source window. It is unavailable via context menu when nothing is selected in the Source window. When selected from the Debug menu or toolbar, it will populate with the selected text in the Source window, or if nothing is selected, it will open empty.

Vera Interactive Debugger 11-30

When editing the fields: The interface name field is required. When set to CLOCK, the system clock is chosen. The Cycles To Wait field is required and the default is 1. Cycles To Wait specifies the number of cycles to wait before breaking.

Stepping Vera Code


The Vera debugger allows you to debug your Vera code by stepping through it. There are various commands available in the Debug menu and in the toolbar. Each of these commands will stop if a breakpoint is reached. See the Debug Menu and table in the section Menus on page 11-8 for a detailed description or the various step-commands and commands to run the simulator.

Vera Interactive Debugger 11-31

Cross-link to All Windows Stepping the simulator will update all windows. The Source window will denote the current line with a blue highlight on the line number. This will also move the Source window cursor to that line. The Local Watch window will update the variables and values with the current stack frame while stepping. The previous stack frames will be available in the Context drop-down list. The Global Watch window will update its values in all tabs based on the current stack frame while stepping. The Call Stack in the Project Workspace window will update by adding frames or changing threads while line stepping. The ITCs in the Project Workspace window will update based on created or destroyed items while stepping.

Watching Variables and Expressions


While debugging, you will likely want to watch variables and create and watch expressions. This can be done in the Local Watch window or the Global Watch window. The global watch window provides you three Watch tabs to organize your views. The Local Watch window is dynamic and will change frame and variables. To keep a variable in view regardless of the current stack frame, you will need to add a Global Watch and view it in a Watch tab of the Global Watch window.

Vera Interactive Debugger 11-32

Expressions can only be watched in the Watch tabs of the Global Watch window. See Global Watch Window on page 11-24 for a description of how to create an expression to watch. ITC items can be watched in the Meta Watch tab of the Global Watch window. See the ITC view or Call Stack view under the Project Workspace Window on page 11-13 to see how to add.

Forcing a Value
While debugging, you may want to force a variable to some value. This forced value will remain until it is overwritten by the code or another value is forced. Selecting Set Value brings up the following dialog. Edit any fields, and click Accept to set the value in Vera. If the assignment is valid, the value will be changed. Otherwise, an error pops up to explain why it was not valid. Clicking Cancel discards any changes in this dialog and closes it. When selected from the context menu in the Source window, it will populate the Variable field with the selected text in the Source window. It is unavailable via context menu when nothing is selected in the Source window. When selected from the Debug menu or toolbar, it will populate with the selected text in the Source window, or if nothing is selected, it will open empty.

Vera Interactive Debugger 11-33

Cross-link to Watch Windows If the assignment is valid, the Local and Global watch windows will update the value if the variable is displayed there.

Finding a String in Source


The Vera debugger allows you to search for strings in the Source and Log windows. The Find dialog will remember the last string you searched for and populate the Search String field with it. Strings you previously searched for remain available in the Search String drop down. Selecting Edit-Find from the menu or toolbar brings up the following dialog.

Vera Interactive Debugger 11-34

Search String drop down holds list of searched strings

To find a string, 1. If multiple Source windows are open, click in the one you want to search, to make it active. Subsequent Next and Prev searches will be locked to that window. 2. Bring up the Find dialog and enter the string to search for. 3. Choose any options for matching case, whole word, or search direction. 4. Click Find. The Find dialog will remain open. Your string will be highlighted as selected text if it was found, or an information box will pop up if end of file was reached and no more occurrences were found. 5. Click Close to close this dialog. To change the search string, either edit the Search String field, or select a previously searched string from the drop-down list. The Find dialog may also be used on the Log Window. To search the Log Window, left click in it to give it the keyboard focus before bringing up the Find dialog.
Vera Interactive Debugger 11-35

Preferences and Fonts


The Vera debugger allows you to set various preferences and select a different font to override tool defaults. Selecting Options-Preferences from the menu brings up the following dialog

Array Element Display Limit This controls the number of array elements allowed to display in the Watch windows, starting with the smallest array index. The default is to display the first 50.
Vera Interactive Debugger 11-36

Call Stack Depth Limit This controls the number of frames to display in a call stack. The default is to display the last 100. Default Radices This is a system-wide setting that specifies the default radix for the debugger. The defaults are to display Integers and Enums as Decimal and Bit Vectors as binary. When a watch variable is added, it displays with the default radix. Source Window Tab Width This controls the width of the tab character. The default is 8 spaces to insert per tab character. Center Current Line When this item is checked, the current line will be centered in the source window when the simulation stops. If this item is unchecked, the current line will be made visible, but it will not be automatically centered. Checking this item will also automatically center lines that are found during string searches initiated by the Find dialog. Right Justify Values When this item is checked, variable values shown in the watch windows are right justified so that the right-most portion of the value is always visible. Uncheck this item to left justify values so that the left-most portion is always visible. Restore Source Window, Breakpoints and Global Watch You can control some of what is saved in the settings file to be restored at the next session.

Vera Interactive Debugger 11-37

When Restore Source Window is checked, the Vera debugger will save the size and position of source windows. When Restore Breakpoints is checked, the Vera debugger will save all breakpoints that are defined. Though, expression breakpoints are not saved or restored. When Global Watch is checked, the Vera debugger will save all expressions that are defined and listed in the Global Watch window. Log File Poll Interval This controls the frequency for polling the file displayed in the Log Window. By default, open log files are polled every 200 milliseconds for new entries. Selecting Options-Fonts from the menu brings up the following dialog. Select the desired font changes via this dialog and click OK to apply them. Click Cancel to close the dialog without changes.

Vera Interactive Debugger 11-38

Debugger Settings File


The settings file stores the breakpoints, global watch expressions, window layout and preferences from the last debugger session. When the debugger quits, it always saves the settings in the file $cwd/vera_debugger_rc. When the debugger starts, it searches for the settings file in the following order: 1. $cwd/vera_debugger_rc, 2. $HOME/vera_debugger_rc, or 3. $HOME/.qt/qdbgrc. An alternative name for the settings file may be specified with the VERA_DEBUGGER_RC environment variable.

Vera Interactive Debugger 11-39

The loading of settings file can be suppressed by setting the VERA_IGNORE_DEBUGGER_RC environment variable.

Displaying the simulation log file


The debugger can display the simulation log file and update its display as the file grows.The debugger displays the log in a horizontal docking window along the bottom of the top window. By default, the log file is not shown. There are two ways to enable displaying the log: Use the +vera_debug_show_log runtime option. Enable the LogWindow using the View menu.

Enabling the LogWindow


A log file maybe viewed even if the +vera_debug_show_log option is omitted. Go to View-LogWindow. The LogWindow menu item toggles the display of the Log Window on and off. Once the Log Window is visible, its context menu can be used to load any log file. The context menu has controls to:
Clear Close File Goto Load File Clears the Log Window and only subsequent log entries will be displayed. Clears the Log Window and closes the log file. The window will remain empty until a new log file is loaded. Scrolls the Log Window to the specified line number. Clears the Log Window, and loads a new log file (the old file is closed). The window will be updated whenever the new log file grows.

Vera Interactive Debugger 11-40

Find

Searches the Log Window for string matches

Each main window may load and track a separate log file. The Find toolbutton and Edit-Find menu item now operate on either the Log Window or source windows. If the Log Window has the keyboard focus (for example, text was just selected in the Log Window), the Find dialog will operate on the Log Window; otherwise, it operates on the active source window. The interval for polling the log file for new entries can be configured with the Options-Preferences dialog.

Vera Interactive Debugger 11-41

Vera Interactive Debugger 11-42

12
Vera Waveform Interface 12
OpenVera interface signals, global variables and class properties can be plotted and displayed concurrently with the HDL design signals. The waveform information is stored in a waveform display file. The waveform display file can be created in formats supported by the following waveform display tools: VirSim, which is included with both VCS and Scirocco, Debussy, MTI ModelSim

This chapter includes: OpenVera Plot Declaration OpenVera Plot Control Plotting for VirSim Waveform Tool

Vera Waveform Interface 12-1

Plotting for MTI-ModelSim Waveform Tool Plotting for Novas-Debussy Waveform Tool

OpenVera Plot Declaration


The vera_plot() system task is used to plot desired variables. Once a variable is marked for plotting, its value is saved into a waveform display file every clock cycle. The vera_plot() statement is placed where plotting should begin, usually at the beginning of an OpenVera program. When vera_plot() is used, the -g compiler option must be included. Syntax
task vera_plot(string filename, integer format, string variable, integer mode, "dump=TYPE [,TYPE]");

filename
Is the name of the file in which waveform data are stored. The value can be overridden by the vera_plot runtime option.

Vera Waveform Interface 12-2

format:
Is the format in which the waveform display file is dumped. It can be any of the following: VIRSIM, DEBUSSY, or MTI.
Format VIRSIM DEBUSSY MTI Waveform Format of Generated File vpd, VCD+ FSDB wlf

variable
Is a regular expression or normal string that specifies the variables to be displayed. Hierarchical path and array elements can be used in a normal string specification. For example:
vera_plot("myverafile",MTI,".*", 1); // plot Vera global variables vera_plot("myverafile",MTI" "obj.child_obj.i", 0); // String mode -> plot the variable specified by the //path: "obj.child_obj.i"

Note: Debussy supports the filters, scope_depth_limit and size_limit. Virsim supports scope_depth_limit: scope_depth_limit Specifies the maximum number of nested scopes that would be dumped into the fsdb file. The default value of scope_depth_limit is 5. To specify an infinite scope_depth_limit, explicitly switch it off: vera_plot(scope_depth_limit = *); Use object_print() to view deeply nested scopes.

Vera Waveform Interface 12-3

size_limit Specifies the maximum size (in MB) of the dump file. size_limit is not enabled by default. Example:
vera_plot("plot", DEBUSSY, ".*", 1, "dump = bit, array; scope_depth_limit = 15; size_limit = 20");

mode
Is 1 if the string argument is to be interpreted as regular expression, otherwise it should be 0.
Mode 0 1 Description displays variables matching the exact name specified in the variable argument. displays all variables matching the regular expression specified in the variable argument.

TYPE An optional argument that is only supported for VirSim, Debussy and MTI waveform display tools. Specifies the data types of all plotable variables in an OpenVera program for waveform plotting. Multiple data types can be specified. Use a comma (,) to separate a sequence of data types. The valid data types are: integer, reg/bit, enum, class, port, array, assoc_array When array is specified, fixed-sized arrays of the other data types listed are plotted. When assoc_array is specified, associative arrays of the other data types listed are plotted. When there are multiple vera_plot() calls, the TYPE attributes given in each call are mutually exclusive and therefore not a union of the attributes of the previous calls.

Vera Waveform Interface 12-4

Note: When using vera_plot() to plot virtual ports, all signals will have a bit width of 128 bits regardless of the bit width of the signal being plotted. For example, a one bit clock will show up as a 128 bit bus on the waveform.

vera_plot() Examples
Example 12-1 Using the scope_depth_limit filter
class A { integer data; A next; } ... A a = new(0); a.next = new(1); a.next.next = new(2); ... a.next.next.next.next.next = new(5); vera_plot("plot", DEBUSSY, ".*", 1, "scope_depth_limit = 5"); // It will dump a.next.next.next.next (4 next's) // It will NOT dump a.next.next.next.next.next (5 next's)

Example 12-2 Using the size_limit filter


vera_plot("plot", DEBUSSY, ".*", 1, "size_limit = 15"); // This would limit the size of the file "plot.fsdb" to 15 MB. // The dump after 15 MB would overwrite the existing dump // thereby storing the "last" 15MB of dump.

Example 12-3 Dump type, scope_depth_limit and size_limit can occur in any order
vera_plot("plot", DEBUSSY, ".*", 1); vera_plot("plot", DEBUSSY, ".*", 1, "dump = bit, assoc_array"); vera_plot("plot", DEBUSSY, ".*", 1, "scope_depth_limit = 8"); vera_plot("plot", DEBUSSY, ".*", 1, "size_limit = 15"); vera_plot("plot", DEBUSSY, ".*", 1, "dump = bit, assoc_array; size_limit = 15"); vera_plot("plot", DEBUSSY, ".*", 1, "size_limit = 15; dump = bit, assoc_array"); vera_plot("plot", DEBUSSY, ".*", 1, "scope_depth_limit = 8; dump = bit, assoc_array; size_limit = 15");

Vera Waveform Interface 12-5

Example 12-4 Plotting associative arrays of integers


vera_plot("plot",VIRSIM, ".*",1, "dump=assoc_array, integer");

Example 12-5 Statements that do not plot associative arrays of integers


vera_plot("plot", DEBUSSY, ".*",1, "dump=assoc_array"); vera_plot("plot", DEBUSSY, ".*",1, "dump=integer");

Example 12-6 Plotting associative arrays of bits that are not class members
vera_plot("plot", VIRSIM, ".*",1, "dump=class,assoc_array, reg");

Example 12-7 Plotting all OpenVera global variables and interface signals
vera_plot("vera",VIRSIM, ".*", 1);

Example 12-8 Plotting the variable or interface signals with the name IFC_clk;
vera_plot("vera_ifc", VIRSIM, "IFC_clk", 0);

Example 12-9 Plotting the intarr property of the object in the array element pkt_arry[1]
vera_plot("vera_var", VIRSIM, "pkt_array[1].intarr", 0);

If an array is passed to the vera_plot() task call, all elements of the array are saved into the waveform display file. If a class is passed, only the immediate properties of the class are saved into the waveform display file (that is, properties of any subclasses are ignored).
vera_plot("vera_var", VIRSIM, "pkt_array", 0);

Vera Waveform Interface 12-6

vera_plot() Summary
OpenVera supports the following: plotting of variables that are defined inside a class and are marked as local, public, protected, static or with no keywords plotting of variables that are defined inside a class and are marked as static is supported only for the VirSim and Debussy formats. plotting of global variables specified as a string or regular expression.

OpenVera does not support the plotting of variables that are defined inside a task or function (that is, local variables).

Supported Data Types


Table 12-1 lists the data types supported by VirSim, Debussy, and MTI.

Table 12-1 Data Types Supported by VirSim, Debussy and MTI


Data Types integer reg/bit bit-vector enum port class object static members in class objects
Single dimensional arrays:

VirSim Yes Yes Yes Yes Yes Yes Yes

Debussy Yes Yes Yes Yes Yes Yes Yes

MTI Yes Yes Yes Yes Yes Yes no

Vera Waveform Interface 12-7

Table 12-1 Data Types Supported by VirSim, Debussy and MTI


Data Types integer reg/ bit bit-vector enum port class
Multi-dimensional arrays:

VirSim Yes Yes Yes Yes Yes Yes

Debussy Yes Yes Yes Yes Yes Yes

MTI No No No Yes Yes Yes

integer reg/bit bit-vector enum port class


Associative arrays:

Yes Yes Yes Yes Yes Yes

Yes Yes Yes Yes Yes Yes

No No No Yes Yes Yes

integer reg/ bit bit-vector enum port class

Yes Yes Yes Yes Yes Yes

Yes Yes Yes Yes Yes Yes

Yes Yes Yes Yes Yes Yes

Vera Waveform Interface 12-8

OpenVera Plot Control


The vera_dump() system task allows plotting to be enabled or disabled in a post-simulation mode and not in interactive simulation mode. vera_dump() is only supported for VirSim, Debussy and MTI. By default, plotting is enabled when a vera_plot() task is called.

Example 12-10
program test{ .... vera_plot("myvera", DEBUSSY, ".*", 1); // Calling //this sets plotting ON

vera_dump(OFF); repeat (2000) @ (posedge CLOCK); vera_plot("myvera", DEBUSSY, "str", 0); // Switches plotting ON globally for all the preceding //vera_plot() calls including this one .... .... }

Plotting for VirSim Waveform Tool


The Vera-VirSim integration requires access to the VirSim graphical interface, version 4.1.1 or later. This version of VirSim ships with VCS 6.0.1 or later, and Scirocco 2000.02 or later. It can be obtained and installed as a stand-alone product. To use the Vera-VirSim integration, you must have access to the VirSim graphical interface installation and must set the VIRSIMHOME environment variable to point to the VirSim installation directory and put $VIRSIMHOME/bin in the path variable. The interface between Vera and the VirSim graphical interface is a VCD+(VPD) file. During simulation, Vera stores the signals and variable values for each time-stamp in VCD+(VPD) format. VirSim reads the VCD+ file to display the waveform.
Vera Waveform Interface 12-9

Post Simulation Mode


In post simulation mode, the OpenVera program, along with the HDL simulator, is run in batch mode to generate a VCD+ history file containing the testbench results. Then, by invoking VirSim, any number of users can simultaneously analyze the results recorded in the VCD+ file.

Interactive Simulation Mode


In interactive mode, the VirSim user interface updates the waveform at periodic intervals from the VCD+ file generated by Vera. To set the periodic update interval, go to the drop-down menu under File in the VirSim Waveform window, and select Update. The Update window will appear. Enter the time interval and click OK. You can invoke the Vera debugger and step through the OpenVera code, along with plotting the VCD+ file which is periodically read by the VirSim user interface. For debug mode, you have to set the Update interval in the VirSim Waveform. This will determine the frequency at which the waveform is synchronized with the VCD+ file being plotted by Vera. For further information on how to use Vera-VirSim, see the application note entitled Vera-VirSim Waveform Viewer located in $VERA_HOME/app_notes. To plot from Vera to VirSim, add the following to your OpenVera code:
vera_plot("some_file", VIRSIM, ".*", 1);

Vera Waveform Interface 12-10

This plots global variables and objects, including reg/bit, integer, port instance (port p0 = new(); p0 = b0;) class objects (and sub objects), fixed array of objects and enums. Local variables (variables in tasks and functions) cannot be traced. A class object is not ready to be added into the VirSim Waveform window until the class object is new'd. If the user refreshes the VirSim Hierarchy window by dragging File and choosing Reopen, VirSim will be updated and the class objects will appear. To view OpenVera variables from VirSim, drag File in the VirSim Hierarchy window, and select Open > VCD+ Type > some_file.vpd. Click OK, then click on the design hierarchy button (the yellow folder button) at the top left of the Hierarchy window. Choose some_file.vpd. The OpenVera variables will then be visible. The Hierarchy window shows several blocks. One has the name of the program. Beneath the program block is the name of the interface. Clicking on the program name will show the OpenVera global variables. You can drag objects into the VirSim Waveform window. Push the down button that is next to the program name to see OpenVera class objects, ports, enums. You can drag objects into the VirSim Waveform window. After the simulation, vera_dump.vpd will be produced (a .vpd file is a VCD+ file). Use VirSim (vcs -RPP) to view this file (use VCD+).

Plotting for MTI-ModelSim Waveform Tool


When the MTI waveform display format is selected for vera_plot(), a filename.wlf file is created. To view signals and variables in OpenVera and Verilog, load the Verilog dumpfile (vsim.wlf) and the filename.wlf file.

Vera Waveform Interface 12-11

Post Simulation Mode


To view Vera data in post simulation mode, proceed as follows: 1. Add the following system task to the beginning of the OpenVera program (for example design.vr):
vera_plot("vera_dumpfile", MTI, ".*", 1); // plots all variables

2. Compile the OpenVera code from step 1:


vera -cmp -g -vlog design.vr

This will produce design.vro. If the design.vr contains the program construct, a design_shell.v will be generated. You must use the -g Vera compile option so as to get the vera_plot dump. 3. Compile the all needed Verilog code, including the design, the testbench, and the OpenVera shell files using MTI-ModelSim vlog. 4. Run an MTI-ModelSim simulation in batch mode.
vsim -c design_test_top -do "add log -r /*; run -a ; quit f"\ +vera_load=design.vro

5. Invoke MTI-ModelSim GUI and Waveform Viewer:


vsim -do "view wave; view signals"

6. Add the OpenVera signals and variables to the MTI-ModelSim Waveform View: - In the MTI-ModelSim Main window, choose File > Open > File. - Type in vera_dumpfile.wlf. - In the MTI-ModelSim Signals window, choose View > Wave > Signals in Design.

Vera Waveform Interface 12-12

You should be able to see all the OpenVera signals and variables plotted via vera_plot(). 7. Add the Verilog signals and variables to the MTI-ModelSim Waveform View: - In the MTI-ModelSim Main window, choose File > Open > File. - Type in vsim.wlf. - In the MTI-ModelSim Signals window, choose View > Wave > Signals in Design. You should be able to see all the OpenVera signals and variables plotted via vera_plot().

Limitations
The following limitations apply when plotting for MTI-ModelSim: Associative arrays are displayed having a scope for each associative array with the element index attached with an underscore. For example:
integer AAInt[] AAInt[7] = 1;

AAInt[7] will be displayed as AAInt_7 inside scope AAInt. vera_plot() can be called multiple times in an OpenVera program however, the same output filename must be used. That is, only one WLF file per OpenVera main is allowed. vera_plot() does not support string mode for the Vera 5.1.0 release. That is, mode option 0 is not supported.

Vera Waveform Interface 12-13

vera_plot() does not work with OpenVera linked lists.

Plotting for Novas-Debussy Waveform Tool


When the Debussy waveform display format is selected for vera_plot(), a filename.fsdb file is created. To view signals and variables in OpenVera and Verilog, load the Verilog dumpfile and the filename.fsdb file. When using vera_plot() in interactive simulation mode, the runtime option, +vera_interactive_plot, must be specified, otherwise data is captured in post-processing mode only. Note: The Debussy FSDB Writer versions 5.0 and 5.1 are shipped with the Vera installation. The default library is Debussy FSDB Writer 5.0. This library will work with the Debussy GUI version 5.0 or later. For 5.1 or later, use the following environment variables to select different versions of the FSDB Writer for the VERA FSDB plot. Setting DEBUSSY_VERSION to 5.1 loads the Debussy 5.1 FSDB Writer. Setting DEBUSSY_VERSION to 5.0, which is the default setting, picks up the Debussy 5.0 FSDB Writer. Setting DEBUSSY_VERA to the absolute path of the library libnffw.so overrides the above settings. This may be needed if you are using a different version of the Debussy user interface (for example, version 5.2).

For example:
setenv DEBUSSY_VERA $DEBUSSY_HOME/share/ \ FsdbWriter/SOLARIS2/libnffw.so

Vera Waveform Interface 12-14

Post Simulation Mode


To view the simulation data in post-simulation mode, proceed as follows: 1. In your Verilog code (for example, design.test_top.v), add the following code so that the Verilog signal can be plotted.
initial begin $dumpvars; end

During your Verilog simulation, a file called verilog.dump is created. This file will contain the signal output from the Verilog design. 2. Add the following system task to the beginning of the OpenVera program (for example, design.vr):
vera_plot("vera_dumpfile", DEBUSSY, ".*", 1); //plots all variables

3. Compile the OpenVera code from the previous step:


vera -cmp -g -vlog design.vr

You must use the g compile option. This will produce the file design.vro. If your design.vr file contains the program construct, a design_shell.v file will be generated. 4. Compile the above testbench Verilog code (file design.test_top.v) along with the Verilog design and the OpenVera shell file:
vcs -vera design.test_top.v design.v design_shell.v

This example uses VCS so an executable called simv will be produced.

Vera Waveform Interface 12-15

5. Run a Verilog/Vera simulation. A vera_dumpfile.fsdb will be created. In this example, VCS is used:
simv +vera_load=design.vro

6. Invoke Novas-Debussy. To view OpenVera signals in Debussy, do the following: In the Debussy:nTrace window, choose Tools > New Waveforms. This opens the Debussy:nWave window. In the Debussy:nWave window, choose File > Open. Change the Filter on the lower right hand corner from *.fsdb to *, then double-click on vera_dumpfile.fsdb. In the Debussy:nWave window, choose Signal > Get All Signals. This will display all the OpenVera signals found by vera_plot(vera_dumpfile, DEBUSSY, .*, 1).

To view the Verilog signals on the same Debussy waveform, do the following: In the Debussy:nWave window (where the OpenVera signals are currently displayed), choose File > Open and then double-click on verilog_dumpfile. In the Debussy:nWave window, choose Signal > Get All Signals. This will display all of the Verilog signals.

Interactive Simulation Mode


It is useful to run a simulation in interactive mode using the Vera debugger. You can display the OpenVera signals as you step through the simulation.

Vera Waveform Interface 12-16

To start the Vera debugger and also enable interactive waveform plotting to DEBUSSY, use the +vera_debug_on_start and +vera_interactive_plot runtime options. The following is an example of how to do this with VCS:
simv +vera_load=design.vro +vera_interactive_plot \ +vera_debug_on_start

If the Verilog simulator you are using supports updating the dump file during interactive simulation, you can display Verilog signals along with OpenVera.

Limitations
The following limitations apply when plotting for Novas-Debussy: Disabling of invalid variables is shown by the display of - Dashes for bit-vectors - VERA_UNDEFINED for enums - The minimum value for integers (for example, -2147...) Associative arrays are displayed having a scope for each associative array with the element index attached with an underscore.

Example 12-11
integer AAInt[]; AAInt[7] = 1;

AAInt[7] will be displayed as AAInt_7 inside scope AAInt. vera_plot() can be called multiple times but you must use the same dumpfile name. This means you can have only one FSDB file per OpenVera program.
Vera Waveform Interface 12-17

Plotting in the post processing mode only. But waveforms can be viewed on-line during simulation by using the AutoUpdate feature of Novas-Debussy which refreshes waveforms continuously as and when the dump files are updated. vera_plot() does not work with OpenVera linked-lists. Due to a limitation in Novas-Debussy, OpenVera profiling features cannot be used in conjunction with Debussy waveform capture.

Vera Waveform Interface 12-18

13
Project-Based Testbenches 13
The Vera project-based configuration supports the creation of testbenches with single and multiple Vera main programs. In this configuration, each Vera main program is treated as a module that can be instantiated multiple times and then run concurrently in a single simulation. To run a Vera project-based simulation requires the following files: a Vera project file (.proj) (see Vera Project File on page 13-2) a configuration file (.vcon) for each Vera main program (see Vera Configuration File on page 13-3) all relevant Vera object files (.vro) (see Vera Object Files on page 13-11)

Project-Based Testbenches 13-1

Vera Project File


The Vera project file specifies the Vera main programs that are used in the simulation. A list of configuration and object files must be declared for each Vera main program. The syntax for the Vera project file is:
main module1_name module1_name.vcon module1_object1.vro ... module1_objectN.vro ... main moduleN_name moduleN_name.vcon moduleN_object1.vro ... moduleN_objectN.vro

Each declaration corresponds to a Vera main program and begins with the main keyword followed by a module name. The module name is the name of a Vera program. The file module_name.vcon is the configuration file that specifies the signal connections. The module_object.vro is a Vera object file. A module_name.vrl file can be used in place of the Vera object files. The project file can contain Vera pre-processor directives and macros such as #include and #define. Normal Vera comments (// and /* ... */) can also be used in the project file.

Project-Based Testbenches 13-2

Vera Configuration File


The Vera configuration file (.vcon) specifies how signals are connected between Vera and the HDL design. This makes it possible for you to develop the Vera source code independently of the actual interface signal connections. Since direct node connection is carried out in the .vcon file, the Vera and DUT source code does not have to be recompiled when the signal connections are changed. The .vcon files signal connection specifications override the specifications in the Vera programs interface declarations. Vera loads the .vcon file and runs it through the preprocessor. Preprocessor definitions (for example, #ifdef, #ifndef, #endif) and comments can be included in the .vcon file. The syntax for a configuration file is:
timescale timescale_statement clock clock_statement connect connect_statement veritask veritask_statement

These statements are described in the following sections.

Timescale Statement
Sampling and drive delays are specified in Vera as integers. The Vera/simulator interface interprets these integers in the timescale of the Vera shell. If a specific resolution is needed, you can specify this with a timescale statement in a Vera configuration (.vcon) file.

Project-Based Testbenches 13-3

The timescale statement is optional. If you do not include a timescale statement in the configuration file, the Verilog simulator will use the timescale value declared in the most recently compiled .v file. Syntax
timescale integer multiplier /integer multiplier

integer
Is a valid integer value; either 1, 10, or 100.

multiplier
Is a time unit multiplier: one of f, p, n, u, m or s (corresponding to femto, pico, nano, micro, and milli) followed by "s" (meaning seconds). There must not be any spaces between the integer and the multiplier in the .vcon file. Examples:
timescale 100ps/10ps timescale 1ns/100ps timescale 10ns/10ns

The 100ps, 1ns, and 10ns preceding the / provide the scale factor for the delay numbers in the Vera shell, which comes from the Vera program. The 10ps, 100ps, and 10ps following the / affects the maximum granularity of the simulation time step. Note: VHDL bridges ignore the integer and multiplier to the right of the / character.

Project-Based Testbenches 13-4

Clock Statement
The clock statement creates a clock generator in the Vera shell file, which drives the specified Vera clock. Syntax
clock clock_name period period_number offset offset start initial_value

clock_name
Is the name of the Vera clock. It is specified as either SystemClock or interface_name.clock_name.

period_number
Specifies the cycle length for the clock in the timescale of the shell.

offset
Sets the delay before the clock changes for the first time. The default is 0.

initial_value
Is the clock start value (either 0 or 1). The default is 0.

Clock Port
If a clock signal is not generated by a clock statement and it is not connected to any HDL node through a connect statement (see Connect Statement on page 13-6), the generated Vera shell file includes an input port for that clock signal.

Project-Based Testbenches 13-5

Clock Alias Statement


The clock_alias statement aliases a Vera clock to another Vera clock. Syntax
clock_alias clock_name1 = clock_name2

clock_name1
Is the name of the Vera clock to be made an alias. This clock cannot also have a clock statement because two clocks would then be assigned to the same clock name. Such an assignment would generate compilation errors.

clock_name2
Is the name of the Vera clock to which the clock is to be made an alias.

Connect Statement
The connect statement connects a Vera interface signal or interface clock to a specified HDL node. Syntax
connect [direction] vera_name ="HDL_path_or_type" skew skew_value

or
connect [direction] vera_name = "HDL_path_or_type" surrx_token(time_to_x, time_to_value)

Project-Based Testbenches 13-6

Note: The connect statement does not end with a semi-colon (;). where:

direction
is a direction; one of: in, input, out, output, or inout: - in or input specifies clocks and signals into Vera from the DUT. - out or output specifies clocks and signals out from Vera into the DUT. - inout specifies bidirectional signals. The direction is checked against the direction specified in the interface. Mismatches result in compilation errors. If the direction is not specified, the direction is taken from the Vera interface. The direction for Vera clocks is ignored.

vera_name
Is the name of the Vera signal you are connecting to the DUT. The format for the name is interface_name.signal_name, where the interface and signal are specified in the interface specification.

HDL_path_or_type
Is the name of the HDL node to which the Vera signal is being connected. It should include the HDL hierarchical path. This string overrides any hdl_node option in the interface signal definition. If the string specifies only an HDL_type, or if the HDL_path_or_type string is blank, the interface signal becomes a port-connected interface signal.

Project-Based Testbenches 13-7

Note: A string specifies an hdl_type by enclosing it in curly braces, {}. Also, the interface signal need not have had an hdl_node phrase in its original specification.

skew
Specifies the skew type, either: iskew (input skew) or oskew (output skew). The default is no skew.

skew_value
Is the length of the skew type specified. If you specify input skew, the skew_value should be 0 or negative. If you specify output skew, the skew_value should be 0 or positive. The default skew_value is 0.

surrx_token
Is a valid surround-by-X token: surrx, surrxR, surrxF, surrxD, or surrxZ.

time_to_x
Specifies the time after the driving clock edge that elapses before the signal is driven to X. This value must be an integer greater than 0. The time units used for the delay are the same as the HDL timescale being used.

time_to_value
Specifies the time after the driving clock edge that elapses before the signal is driven to its final value. This value must be an integer greater than 0 and greater than the time_to_x value. The time units used for the delay are the same as the HDL timescale being used.

Project-Based Testbenches 13-8

Note: The SystemClock should NOT be defined as an inout signal using the connect command. Define the SystemClock using the clock command.

Veritask Statement
The veritask statement maps a Vera task to an HDL task. It overrides the hdl_task statement in the Vera sources. This statement is optional. If it is missing for an hdl_task, the original path from the hdl_task statement in the Vera source code is used. Syntax
veritask vera_task_name = HDL_task_name

vera_task_name
Is the name of the Vera task being mapped to an HDL task.

HDL_task_name
Is the HDL name of the task. It should include the HDL hierarchal path. To use the veritask statement, you must declare the hdl_task in the source code using an arbitrary pathname. Then, in the configuration file, you must specify the actual task pathname. For example, suppose the Verilog task myTask is declared in the Vera sources as:
hdl_task myTask(integer a, integer b, integer c) "dummy";

Project-Based Testbenches 13-9

Given this hdl_task declaration, the configuration file can include this veritask statement:
veritask myTask = "top.dut.myTask"

Template for Vera Configuration File


The Vera compilation option, -vcon, creates a template for a Vera .vcon file. Syntax For Verilog source code:
vera -cmp -vlog | -verilog -vcon filename.vr [output_filename]

For VHDL source code:


vera -cmp -simulator -top -vcon filename.vr [output_filename]

simulator
Is the name of the simulator: mti, nc-vhdl, or sro.

output_filename
Specifies an optional alternative output file name for the generated .vcon file. The default file name is filename.vcon. For example, the command:
vera -cmp -verilog -vcon test.vr

generates the filetest.vcon, whereas the command:


vera -cmp -verilog -vcon test.vr new_test

generates the filenew_test.vcon.


Project-Based Testbenches 13-10

Vera Object Files


A Vera object file (.vro) is the binary file created when a Vera source (.vr) file is compiled. All Vera object files relevant to a Vera main program must be listed in the Vera project file.

Project-based Configuration Simulation


To run a project-based configuration simulation: 1. Compile the source code for the individual testbench modules. This generates the Vera object files and shell files required to run the simulation with the testbenches. 2. Create a configuration file for each testbench module. If the Vera source files are available, you can generate a template configuration file by entering the command:
vera -vcon program.vr

where the file program.vr contains the program block for the module. 3. You must then customize the template configuration file as necessary by specifying signal connections, clock periods, and any HDL tasks that need to be defined in the configuration file. It is important that the signals are connected to the correct HDL nodes. 4. Create an overall project file that contains information on all modules necessary for the simulation.

Project-Based Testbenches 13-11

5. Create Vera shell files for each Vera module listed in the project file:
vera -proj file.proj

This generates a Vera shell file called modulename_shell.v for each module (for VHDL flows the name is modulename_proj_shell.vhd). The Vera shell files are used during the Verilog or VHDL compilation. The Vera shell file is generated from the .vro files created when the Vera source code is compiled. 6. Compile the shell files along with the DUT files:
vcs mod1_shell.v ... modN_shell.v dut.v

7. Run the simulation with the vera_pload runtime option (as a plus argument in the command line, or as an option in the vera.ini file):
simv +vera_pload=proj_name.pro

This procedure eliminates the need for a test-top file that instantiates the Vera shell modules. However, you can still use the test-top file approach with a project-based approach by deliberately not specifying connections for Vera interface signals in the .vcon file. Unconnected signals are automatically listed as ports in the Vera shell module. The Vera shell module must then be connected to the rest of the simulation by instantiation. Note: It is possible to mix the two approaches in a single project file where only some testbench modules require instantiation.

Project-Based Testbenches 13-12

Main-Specific Plus Arguments


Runtime options can be specified in the project (.proj) file using the same format that the vera.ini file uses. Runtime options that are specified in the project file apply only to the specific main block in which they are specified. These runtime options are ignored if they are specified within the project file:
vera_mload_define vera_pload_define vera_load vera_mload vera_pload vera_enable_mprint

This is an example of main-specific runtime option definitions:

Example 13-1
main test1 test1.vro test1.vcon vera_random_seed = 100 user_runtime_option = "string value for test1" main test2 test2.vro test2.vcon vera_random_seed = 200 user_runtime_option = "string value for test2"

In this example, all instances of test1 use a random seed value of 100 while all instances of test2 use a random seed value of 200. Additionally, each main uses the value of user_runtime_option specified within its main block.

Project-Based Testbenches 13-13

Instance-Specific Properties
When more than one instance of a given main block is instantiated in a single simulation, Vera assigns unique instance ID numbers to each instance. The instances are numbers sequentially, starting at 0. In the project file, you can assign a runtime option to a specific instance of a main block by adding an instance number to the runtime option name using this format:
runtime_option_name[instance_number] = runtime_option_value

where instance_number must be an unsigned integer. A runtime argument with an instance number applies only to that instance of the main block. A runtime option with the instance number omitted applies to all instances of the main block. The instance number can be used with any of the valid runtime option definition formats. The following is an example of a main block using instance numbers:

Example 13-2
main test1 vera_random_seed[0] = 100 // applies to 1st instance of test1 vera_random_seed[1] = 200 // applies to 2nd instance of test1 vera_random_seed[2] = 300 // applies to 3rd instance of test1

Project-Based Testbenches 13-14

Mixed HDL Support


Vera project-based configuration supports mixed design language (Verilog and VHDL). During the vera -proj invocation, you must insert an additional switch so that the proper Vera shell is created to support mixed design language simulation. If Verilog is the topmost language, use:
vera -proj -vcs_mx filename.proj

If VHDL is the topmost language, use:


vera -proj -sro_mx filename.proj

Project-Based Testbenches 13-15

Project-Based Testbenches 13-16

14
Testbenches for Verification Intellectual Property 14
Vera offers a Vera Core license that allows an IP creator to develop verification components, such as a bus master or a bus slave, that can be packaged to run without the user having a Vera license. The packaged IP is referred to as Verification Intellectual Property (VIP). This chapter describes the VIP files, the contents of VIP packages and their use, and how to create VIP in the following sections: Verification IP Files Setting Up a VIP Installation Typical VIP Contents Writing a VIP Testbench Creating Verification IP

Testbenches for Verification Intellectual Property 14-1

Verification IP Files
VIP files are normal OpenVera source files that have been tagged with a special comment that permits them to be compiled and simulated without any Vera licensing. VIP files may also be encrypted. Instead of distributing Vera object code (.vro) files or standard source code (.vr) files, vendors distribute VIP files. An example VIP vendor tree and user directory tree are included in the Vera installation in the directory $VERA_HOME/examples/VIP.

Creating VIP Files


VIP files are created by calling Vera with the -vip switch. This switch converts the input source file into a VIP file. For example, assuming that the Vera source is the file mod.vr, the command to create the VIP from this file would be:

Example 14-1
vera -vip mod.vr

and the resulting file would be called mod.vrp. Note: A Vera CORE license is required to generate a vip file.

Testbenches for Verification Intellectual Property 14-2

Protected VIP Files


The VIP files may optionally be protected. The protection is an encryption that makes it impossible for you to read the files. In addition, the decrypter and pre-processor are linked directly into a special version of the Vera compiler so that no temporary files and pipes are created. If your VIP contains protected files, the directories will contain files with different extensions: the header files will have a .vrip extension instead of .vri the Vera source code file will have a .vrp extension instead of .vr

If your testbench includes protected VIP, debugging is disabled.

Setting Up a VIP Installation


Setting up a VIP installation is typically a procedure that needs to be performed only once. The following actions must be performed: 1. Install the VIP package. This step compiles the Vera libraries onsite and installs the .vro files into the vendor tree (see Figure 14-3 on page 14-6). 2. Set any environment variables and the path for the vendor. Vendor environment variables are used by models to automate the loading of VRO and DirectC libraries (see Automated Loading on page 14-11).

Testbenches for Verification Intellectual Property 14-3

Installing the VIP Package


The installation of a VIP package is normally controlled by an installation script or by a vendor's graphical user interface. To install the package you run the script or start the user interface and proceed as prompted. Regardless of how it is initiated, the installation procedure will: Choose a model configuration. The model installation will contain options for choosing a particular configuration of a model. The configurable parameters may include: - Target simulator - Bus widths - Optional interfaces Create a vendor-specific sub-directory in the testbench directory. Install header files for the models interfaces and bindings. Install a sample Vera testbench. The testbench should contain a program declaration and demonstrate how to create, connect, and control the model. Install a sample makefile that compiles the sample testbench, compiles the shell, and runs the target simulator.

Figure 14-1 shows the layout of the testbench directory after the model setup has been completed ($cwd is used as a shorthand to refer to your testbench directory).

Testbenches for Verification Intellectual Property 14-4

Figure 14-1 A Testbench Directory after Model Setup

Typical VIP Contents


Typically, a VIP package contains the following Vera-specific files: Vera sources for all verification components: .vr and .vri (header) files. Vera DirectC libraries for all platforms: dynamically linked object files; for example, Solaris .so files

Vera object (.vro) files are not shipped; rather, they are generated as part of the installation procedure. Figure 14-2 shows a typical installation tree for a VIP package.

Figure 14-2 A Typical VIP Vendor Installation Tree


The tree supports multiple platforms. Dynamically loaded Vera DirectC libraries are shipped in platform-specific directories that follow the naming convention of Vera releases (for example, solaris7). This allows them to be loaded automatically (see Automated Loading on page 14-11).
Testbenches for Verification Intellectual Property 14-5

Figure 14-3 shows the detailed layout of the Vera sub-tree. This sub-tree is partitioned into suite-specific trees and a common tree. Each suite contains all the Vera sources for a family of verification components (amba, pcix, ethernet, and so on).

Figure 14-3 Vera Sub-Tree of a Vendor VIP Installation Tree

The examples, include, and src sub-trees of each suite are fully populated with Vera files: The examples directory contains sample testbenches and makefiles. The include directory contains the unencrypted .vri files (headers) for the .vr files contained in the src directory The src directory contains the encrypted source (.vr) files for each verification component of the suite.

Testbenches for Verification Intellectual Property 14-6

Generated Files
The files in the src directory are compiled into the lib directory during installation. If the models support many configurations, the compilation of configurable sources may be deferred until the model installation phase. For example, the site-wide installation may compile only utility libraries, and the installation for each model will compile the model files on demand. The lib directory holds versioned object (.vro) files that are created by the installation script. The object code (.vro) files are platform-independent and therefore do not need to be separated into platform-specific directories.

Header Files
Typically, at least two header files are installed in the include directory for each model configuration:

model.vri
contains the class and port declarations for the model.

model_load.vri
automates the loading of the models VRO and DirectC libraries using the vendors environment variables (see Automated Loading on page 14-11). A third header may be provided but it should not be located in the include directory:

model_ifc.vri
contains the interface and bind declarations for the model.

Testbenches for Verification Intellectual Property 14-7

Because you may want to edit the interface declarations to, for example, modify skew settings and add hdl_node connections, this file is not located in the include directory but will have been installed in the testbench directory during the model installation phase.

Documentation
Obviously, VIP vendors document their own verification components, but because these components are written in Vera, the vendor also provides some Vera-specific documentation. At the minimum, the following Vera-specific documentation should have been provided: Instructions on how to download Vera Details of where to find the Vera installation instructions Information concerning compatible Vera versions (such as Vera 5.1.0 or newer) A description of how the Vera installation interacts with the VIP installation (for example, a note that Vera must be installed first) Instructions on how to integrate the models into a Vera testbench Instructions on how to simulate the models with a Vera testbench

Writing a VIP Testbench


Verification IP is presented as a Vera class library. From this library the testbench creates a class object for each model you require. Both the testbench and the models are written in Vera.

Testbenches for Verification Intellectual Property 14-8

Figure 14-4 shows a possible SOC configuration. Each verification model is a separate class object created and controlled by the testbench.

Figure 14-4 SOC Configuration for a VIP Testbench

The testbench creates the models, connects them to the HDL via port variables, and controls them via method calls. A single shell is created because a single Vera program is used for both the testbench and models. After the testbench has been written and compiled, the HDL simulation is executed.
Testbenches for Verification Intellectual Property 14-9

At the beginning of the simulation, the testbench creates the verification models and connects them to the DUT via port variables. The testbench then initializes the models and runs one or more tests. The sample testbench installed during the installation can be used as a starting point for writing your own VIP testbench.

Editing the Makefile


Compiling the testbench produces an HDL shell file. This shell is an HDL module that connects the Vera testbench to the DUT. Instantiating the shell in the DUT automatically plugs Vera into the HDL simulation. The shell can connect to DUT signals either through ports or through cross-module-references (XMRs): Connecting via shell ports; a top module is required to instantiate the shell and wire the DUT and shell ports together. This is the default connection method. Connecting through XMRs: the Vera interfaces are connected to the HDL with the hdl_node option; the generated shell will connect using XMRs and may not have any ports. If you wish to connect via XMRs, you must edit the models interface file The compilation and elaboration of the shell within the HDL simulation is controlled by a makefile. The makefile has to be edited to add commands that compile and elaborate the shell along with the DUT files. The sample makefile installed during the installation of the VIP can be used as a starting point.

Testbenches for Verification Intellectual Property 14-10

Configuring the VIP Models


Each VIP model may have a variety of configurations, such as an 8-bit and a 16-bit address version, and each variation will have uniquely named globals and uniquely named files. The files in the examples, include, and lib directories, are fully configured so that, for example, there will be a separate set of header files and VRO files for the 8-bit and 16-bit versions of a model. For configurations that vary only in bus size, the number of files may have been reduced by the use of a single set of header and VRO files that support the maximum size. For example, all read and write command methods can accept 16-bit addresses, although the IP may be connected to an address bus that is 8 bits wide. Models are normally configured via pre-processor directives. For example, the following command shows how a pre-processor symbol can be used to select the width of an address bus:
vera -cmp -vip -DADDR_WIDTH=16 my.vip

Consult the VIP vendors documentation for details of what headers and preprocessor directives must be included in the program file to use a model.

Automated Loading
As mentioned earlier, each model is responsible for loading its own object code (.vro) files and DirectC libraries. Models self-load by declaring special attributes within the Vera program file. For example, using attributes, load files can be specified in the program itself:
vera_attribute RTIME_LOAD_LIST_main = "testbench.vro";

Testbenches for Verification Intellectual Property 14-11

vera_attribute RTIME_LOAD_LIST_pci = "$ABC_HOME/lib/pci.vrl"; program testbench { ...

When the HDL simulation begins, the simulator calls a foreign task inside the shell to load the files. The code shown above creates a shell that loads two files, a local file testbench.vro and a file in the ABC installation pci.vrl. No external configuration files (proj, vcon, ini) or HDL command line options (such as +vera_pload) are needed. Simulation is as easy as entering the following commands:
vera -cmp testbench.vr # create the shell vcs -vera testbench.vshell dut.v # parse and elaborate the shell and dut simv # run the simulation

Attributes can also control the automatic loading of DirectC libraries. The code below is identical to the above example, except that the DirectC library, pci.so, is loaded automatically at runtime.
vera_attribute RTIME_LOAD_LIST_main = "testbench.vro"; vera_attribute RTIME_LOAD_LIST_pci = "$ABC_HOME/lib/pci.vrl"; vera_attribute RTIME_UDF_LIST_pci = \\ "$ABC_HOME/$VERA_PLATFORM/pci.so"; program testbench { ... }

The attributes for loading all the object code (.vro) files and DirectC libraries used by a model should be placed inside the models .vri file; in this example, abc_Xyz8.vri.

Testbenches for Verification Intellectual Property 14-12

Including the .vri in the program file enables the .vro and DirectC libraries to be loaded automatically:
# define INSIDE_PROGRAM_FILE # include "abc_Xyz8.vri" # include "abc/abc_Xyz8_ifc.vri" vera_attribute RTIME_LOAD_LIST_main = "testbench.vro"; program testbench { ... }

Note that the INSIDE_PROGRAM_FILE symbol is defined so that the .vri files define the attributes conditionally. Attributes may only be declared in the program file therefore, in order to share the .vri files between program files and non-program files, the attributes must be conditionally compiled. For example, the loading code inside abc_Xyz8.vri will look something like this:

Example 14-2 Conditionally Compiling Attributes


# ifdef INSIDE_PROGRAM_FILE // Load VROs and UDFs for the model vera_attribute RTIME_LOAD_LIST_abc_Xyz8 = "$ABC_HOME/vera/Xyz8/lib/$VERA_VERSION/Xyz8.vro"; vera_attribute RTIME_UDF_LIST_abc_Xyz8 = "$ABC_HOME/$VERA_PLATFORM/lib/Xyz8.so"; // Different models may share the same utilities. // So load utility VROs and UDFs only once! # ifndef abc_UTIL_VRL # define abc_UTIL_VRL 1 vera_attribute RTIME_LOAD_LIST_abc_utils = "$ABC_HOME/vera/common/utils.vrl";

Testbenches for Verification Intellectual Property 14-13

vera_attribute RTIME_UDF_LIST_abc_udfs = "$ABC_HOME/$VERA_PLATFORM/lib/udfs.so"; #endif //abc_UTIL_VRL #endif //INSIDE_PROGRAM_FILE

Passing Properties via HDL Parameters


Properties can be passed to Vera programs either through files (proj, ini) or through the simulator command line (plusargs). They can also be passed by HDL parameters. For example, this Vera code creates a parameter named logging_mode in the shell with the default value of quiet:
vera_shell_param logging_mode = "quiet";

When the shell is instantiated, you can override the parameter to configure the IP. The Vera code can fetch the value of the parameter at runtime and take appropriate action:
string s; s.bittostr(get_shell_param(STR, "logging_mode")); switch(s) { case "quiet": ... case "normal": ... case "verbose": ... }

Testbenches for Verification Intellectual Property 14-14

C and HDL Testbenches


Vera is the recommended testbench language for controlling Vera IP. This gives you better performance, tighter integration, and advanced testbench capabilities within a pure Vera flow. However, it may be necessary to enable other testbench languages to control the VIP. This section describes how to create VIP that supports Vera, C, and HDL testbenches.

VIP Implementation Types


Vera supports an approach that packages a Vera program like a self-contained HDL model. This enables existing HDL verification models to be replaced with Vera models. Existing HDL verification models have a well-understood usage model. They have the same port list as their matching implementation models, so that all that you are required to do is instantiate the models HDL shell. The configuration of the model is controlled through HDL parameters, control of the model is flexible. To retain this flow and replace the guts of the models with Vera, the loading, configuration, and control of the Vera portion is encapsulated within an HDL shell (see Automated Loading on page 14-11 for a description of how models are load automatically). If both C and HDL testbenches are supported by the VIP, it should be available as both a standalone Vera program and as a Vera class library: The standalone implementation allows HDL and C testbenches to control a Vera model via calls to exported Vera tasks.

Testbenches for Verification Intellectual Property 14-15

In standalone mode, there is a one-to-one relationship between model instances and Vera programs. Each Vera program is independent and each model instance is totally independent. The class library implementation allows Vera testbenches to instantiate a model as a class object and control it via method calls. In class library mode, all model instances created by a particular Vera program share the same static member variables.

C Testbenches
A C testbench controls Vera models using the Vera C-API. The API enables C code to call exported tasks inside each Vera program. The VIP contains a hook that calls your C code at the start of simulation so that it can collect handles to the exported tasks. The hook is a designated DirectC library, and the Vera code will look similar to this:
task $hook(); program MyModel vera_attribute RTIME_UDF_LIST_hook = "$ABC_HOME/$VERA_PLATFORM/hook.so"; { $hook(); ... }

The default hook in the ABC_HOME installation would do nothing, but you can create your own DirectC library and force Vera to load your hook by overriding the RTIME_UDF_LIST_hook parameter:
defparam top.MyModel.RTIME_UDF_LIST_ hook = "./myhook.so";

Testbenches for Verification Intellectual Property 14-16

Figure 14-5 shows a possible SOC configuration for a C testbench.

Figure 14-5 SOC Configuration for a C Testbench

HDL Testbenches
An HDL testbench controls Vera models by calling wrapper tasks inside each Vera shell. In turn, the wrappers execute tasks exported from the Vera model. Each Vera model connects to the HDL via a shell module and runs a separate Vera program. The programs communicate with their shell via PLI. Figure 14-6 shows a possible SOC configuration for an HDL testbench.

Testbenches for Verification Intellectual Property 14-17

Figure 14-6 SOC Configuration for an HDL Testbench

Command Interfaces for C and HDL Testbenches


Controlling a Vera model with a Vera testbench is extremely simple; the model is typically packaged as a Vera class and the transaction tasks are implemented as methods of the class. Verification IP is typically controlled by high level, transaction based testbenches. Rather than force you to use a particular testbench language for controlling the IP, export tasks allow you to control Vera models from both HDL and C testbenches.

Testbenches for Verification Intellectual Property 14-18

Export tasks provide the following features to support HDL and C testbenches: Support for concurrent HDL enabled tasks Support for C enabled tasks Support for string parameters

Support for Concurrent HDL Enabled Tasks. The shells generated by Vera contain wrappers for exported Vera tasks. These wrappers enable HDL testbenches to call tasks within a Vera model. The wrappers support concurrency even if the HDL tasks do not, but the concurrency is limited. An attribute for each task specifies the maximum number of concurrent enablings. For example, the following code creates a wrapper that supports three concurrent enablings for task Foo:
export task Foo() vera_attribute SHELL_MAX_CONCUR = 3 { @(posedge p1.clk); printf("OK\n"); }

A global attribute (for VHDL shells only) specifies the maximum number of instances supported for the Vera model. Unlike Verilog, VHDL wrappers for exported tasks are not encapsulated in the shell module. Consequently, instantiating the shell multiple times does not automatically provide extra handshaking signals for the wrappers, and a hard limit must be set for the number of handshaking signals. The SHELL_MAX_INST attribute specifies that limit. For example, the following code makes Vera create a shell that supports four VHDL instantiations.
vera_attribute SHELL_MAX_INST = 4;

Testbenches for Verification Intellectual Property 14-19

Support for C Enabled Tasks. C testbenches may call Vera export tasks. The export declaration not only permits HDL testbenches to call a Vera task; it also brings in a C-API that enables C-code to call exported tasks. Furthermore, the C-code may begin any number of concurrent calls. When each Vera task completes, the C code is notified via a callback. Support for String Parameters. Exported tasks may have formal string parameters. In Verilog, literal strings are automatically converted to bit-vectors. In VHDL, strings may be passed directly when the parameter is of type string:
export task Foo(string cmd) { switch(cmd) { case "read": ... case "write": ... } }

Mixed Vera Testbenches


This approach mixes standalone models with class object Vera models. Vera models can run as standalone programs each with their own HDL shell and a Vera testbench then controls them through their HDL task interface. The Vera testbench communicates with the models in the same fashion as an HDL testbench. To promote code reuse, the model should always be implemented as Vera classes. This makes it possible to create both standalone and class library solutions that share the maximum amount of code.

Testbenches for Verification Intellectual Property 14-20

Essentially, the code is the same, except that in standalone mode the program that creates the object is provided, and in class library mode you write the program that creates the object. The standalone and class library approaches are not exclusive. You can mix standalone Vera models that communicate through an HDL task interface with other models that are created as class objects. For example, Figure 14-7 shows how a PCI model has been brought into the testbench as a class object, but the other Vera models remain independent, only communicating through HDL tasks and signals.

Figure 14-7 A Mixed Vera Testbench

Testbenches for Verification Intellectual Property 14-21

Collision of the SHELL_MAX_INST attribute should be avoided by preventing its definition when a model is used a class object. This implies that there will either be a separate installation procedure or you must use separate compilation flags when using standalone mode instead of class library mode.

Creating Verification IP
Vera CORE enables full access to all the functionality of Vera. The VIP creator can ship model libraries or full testbench environments. As the user cannot change the VIP code the usual approach is to ship model libraries, which consist of user interfaces (API), functional coverage, and monitors. The VIP testbench can also be included as a compliance suite.

Connection to the Users Testbench


There are a few considerations to review before packaging VIP for delivery. The most important is the environment the customer will be using. For instance, whether the user has access to Vera or only HDL and C. Based on the answer to this question, you need to determine the best way to facilitate the connection of the VIP model to the users testbench. There are two ways to connect the users environment to the VIP creators environment: 1. vshell port connection The Vera shell is instantiated at the top level of the users test environment and the user must create an instance of the shell and wire all the connections.

Testbenches for Verification Intellectual Property 14-22

This method is a flexible solution for both connecting to the users HDL and to the users Vera code, if applicable. Users instantiate the Vera shell into their test environment, which is very similar to creating the test_top.v/vhd file in the VIP creators verification environment.
vera_shell vshell( // Users Connection to Vera (assumes Vera license) .SystemClock ( SystemClock ), .memsys_clk ( clk ), .memsys_reset ( reset ), .memsys_busAddr ( busAddr ), .memsys_busData ( busData ), .memsys_busRdWr_N ( busRdWr_N ), .memsys_adxStrb ( adxStrb ), .memsys_request ( request ), .memsys_grant ( grant ), .memcntlr_probe_clk ( clk), // Custom for VENDOR_NAME_CPU .vendor_name_cpu_clk(clk), .vendor_name_cpu_reset(reset), .vendor_name_cpu_busAddr(busAddr), .vendor_name_cpu_busRdWr_N(busRdWr_N), .vendor_name_cpu_adxStrb(adxStrb), .vendor_name_cpu_request(request), .vendor_name_cpu_grant(grant) );

2. hdl_node method The path of the connection is contained in the Vera interface declaration.

Testbenches for Verification Intellectual Property 14-23

The hdl_node method allows the signal connection to be abstracted since the user does not have to edit the top level testbench. All Vera connections can be handled with hdl_node. However, since the connections are handled in Vera and the user is not allowed to change the Vera VIP code, the signal path must be planned carefully. There are two possibilities to consider: a. The user has Vera. Edit the hdl_node directly in the Vera interface. This is acceptable because a Vera compiler license will be checked out to compile the changes. b. The user does not have Vera. Use a #define clause as illustrated below:
#define HPATH my_test_top interface myInterface { output reset OUTPUT_EDGE OUTPUT_SKEW hdl_node HPATH.reset; . . . }

Note: The quote () must be part of the define statement because in the case of HPATH.reset HPATH will be treated as part of a string and no macro substitution would be made. When using the hdl_node method, the following construct can be used to connect the system clock (note that it must be positioned outside the interface definition):
interface myInterface { ... input clk CLOCK; } hdl_node CLOCK "I_clk";// SystemClock Connection

Testbenches for Verification Intellectual Property 14-24

File Naming Conventions


When creating Vera VIP, you should observe the following naming conventions: source files: filename.vr header files: filename.vri

Developing a VIP Model


Developing a VIP model requires a rigid flow to ensure that the model will work correctly in the users environment. This flow must address the unique naming, instantiation, and installation of the VIP model. This section describes the steps in building the VIP model. The description of the procedure for creating a VIP model is based on a practical example using a simple CPU BFM. The BFM model is available in the Vera tutorial, see $VERA_HOME/tutorial. It is assumed that an existing model is converted into one suitable for external users. The header file for the model is as follows:

Example 14-3 Header File


extern class CPU { rand bit [7:0] address; rand bit [7:0] data; rand integer delay; cpu_bus_arb localarb; constraint del_lt10; task new (cpu_bus_arb arb); task writeOp ( (bit [8:0] addr = 9'h1ff), (bit [8:0] dat = 9'h1ff) );

Testbenches for Verification Intellectual Property 14-25

task readOp ( (bit [8:0] addr = 9'h1ff), (bit [8:0] dat = 9'h1ff) ); task request_bus ( ); task release_bus ( ); }

Avoiding Naming Conflicts


The first step in modifying this model is to ensure that external names in the model are unique so that they will not clash with the users verification environment (see Naming Conventions on page 14-31). The following names must be unique when generating the VIP: classes ports binds interfaces attributes coverage_groups global enums global functions global tasks global variables

Testbenches for Verification Intellectual Property 14-26

For the CPU model, all class, interface, port, and binding names must be modified:
class CPU interface cpu port cpu_bus_arb bind cpu_arb0 bind cpu_arb1 ==> ==> ==> ==> ==> class creator_name_CPU interface creator_name_cpu port creator_name_cpu_bus_arb bind creator_name_cpu_arb0 bind creator_name_cpu_arb1

Connecting to HDL
This example uses the hdl_node method of HDL connection. A #define statement must be used to hold the path to the users DUT, and the user edits the path. You should automate this with scripting during the installation of the model. The following is the new interface declaration:

Example 14-4 Modified Interface Declaration


#define HPATH memsys_test_top interface creator_name_cpu { input clk CLOCK hdl_node HPATH.clk; input reset INPUT_EDGE INPUT_SKEW hdl_node HPATH.reset; . . . } hdl_node CLOCK HPATH.SystemClock;

Automatic Object Loading


You can shield the user from the complexities of object loading with the vera_attribute command. This command allows you to code into the model the names of the .vro and DirectC libraries that are to be loaded automatically.

Testbenches for Verification Intellectual Property 14-27

Automatic loading should be handled within a header file included by the users testbench. If the user has an HDL environment, the header file needs to be included within the same file as the program statement. For this example model, the file creator_name_cpu_load.vri is created:
#ifndef CREATOR_NAME_CPU_LOAD_VRI #define CREATOR_NAME_CPU_LOAD_VRI vera_attribute RTIME_LOAD_LIST_cpu = cpu.vro"; #endif

The vera_attribute RTIME_LOAD_LIST_name must be included for every .vro file you want to load automatically. You supply the name; it should be the same base file name as the .vro file being loaded. After the attribute the .vro filename is enclosed in quotes. Your installation script must define the path to this file name or the user can manually edit the filename in quotes. This is one item that can be changed in a .vrip file. Note that the main program file name is not supplied within the load list because the model will be available to both Vera and HDL users. For HDL users you must create a top-level program that automatically includes the name_load.vri file as well as an attribute to load the top-level program:
#include "creator_name_cpu_load.vri" vera_attribute RTIME_LOAD_LIST_main = "cpu_main.vro" program cpuStandalone { . }

Testbenches for Verification Intellectual Property 14-28

Including Files
When developing models you will most likely be using .vri and .vr file extensions. After compiling with the -vip switch these extensions will be changed automatically to .vrip and .vrp respectively. Your environment will need to be flexible in order to handle these changes without forcing you to recode. The following construct is recommended:
#ifndef DEVELOPMENT_MODE #include filename.vri #else #include filename.vrip #endif

Then while developing the models, you can compile them as follows:
vera -cmp [options] -D DEVELOPMENT_MODE filename.vr

Preventing Multiple Inclusion


All header files should check and prevent multiple file inclusions. Assuming that the file name is creator_name_cpu.vri, the following construct within the file will provide the necessary restrictions:
#ifndef CREATOR_NAME_CPU_VRI #define CREATOR_NAME_CPU_VRI . . . // body of header file #endif

The first time the file is included, the #ifndef clause will evaluate true, define the unique name, and include the header. The next time it is called, it will evaluate false and nothing will be included.

Testbenches for Verification Intellectual Property 14-29

VIP File Generation


Before generating VIP files, completely verify your environment. At the conclusion of the verification process VIP files will be generated. This process involves calling the -vip switch and optionally the -prot switch. The -vip switch converts the file format and the source code remains readable.
vera vip filename.vri

When using the complementary switch prot, the code is converted to VIP format and also encrypted.
vera vip prot filename.vr

The file filename.vri will be converted to filename.vrip, and filename.vr will be converted to filename.vrp You should use -vip for all header files and vip prot for all source files. For debugging purposes do not encrypt header files. When encrypted files are included in a users testbench debugging is disabled.

Deliverable Files
You will need to supply the user with the following files:

modelName.vri
contains all the model-level define statements and class definitions. It is included in the user testbench for access to the model. To create this file, create a header file with the H switch and then copy its contents into the .vri file.

Testbenches for Verification Intellectual Property 14-30

model_name_ifc.vri
contains the interface declaration, the definition for the vendor_name_cpu_bus_arb port and its associated bindings. Users include this file in their test environments when using Vera. Note: The port declarations go in the _ifc file, not in the model header.

modelName_load.vri
contains the automated loading procedures discussed in the next section.

VIP Coding Conventions


To be truly useful, it must be possible to use VIP in a variety of environments, and it is impossible to exercise complete control over those environments. It is therefore essential that VIP code follows a few key coding conventions.

Naming Conventions
When models are distributed as class libraries they share the same global name space and the name of each model must be unique. Further, to prevent name collisions with user code or IP from other sources, each of the following symbols must have a unique prefix or postfix. classes ports binds

Testbenches for Verification Intellectual Property 14-31

interfaces attributes coverage_defs global enums global functions global tasks

Header File Naming


To avoid ambiguity when processing header files, each header file must have a unique prefix or postfix. Furthermore, the header file contents should be bracketed with #ifdef and #endif directives to guarantee that the contents are not processed more than once by each compilation unit.

Version Checking
VIP model code must check whether a compatible version of Vera is being used. The check can be performed either with a shell script at compile time or with preprocessor directives at runtime. Vera Shell Script. The Vera version is reported in a version.minor.patch format, where all 3 fields are integer values. For example, the current version of Vera prints as 6.2.0. A more complete version information is printed when using the -V option. For example, the command vera -V for the current version of Vera prints Vera 6.2.0 ().

Testbenches for Verification Intellectual Property 14-32

VERA_VERSION Environment Variable. The runtime executable defines a VERA_VERSION environment variable that can be referenced in shell parameters:
vera_shell_param version = $VERA_VERSION;

The value of the variable is exactly the same as the output of the vera -v command. Although $VERA_VERSION can be used to perform conditional loading, it is only meant to be used in printing informative messages. You should use the VERA_VMC variable for conditional loading. VERA_VMC Environment Variable. The runtime executable defines the VERA_VMC environment variable. The value of the variable is the version of the Vera virtual machine (that is, the version of the .vro files accepted by the runtime). The value of VERA_VMC tends to change much less frequently than that of VERA_VERSION, which changes with every release. Therefore VERA_VMC is most valuable for conditional loading:
vera_shell_param vera_load_my = \\ $HOME/vros/$VERA_VMC/my.vro

Predefined Preprocessor/Runtime Symbols. Versioning information similar to that supported by the GNU and SunPro C compilers is available from the Vera preprocessor at runtime. The following symbols are predefined by Vera: __VERA_VERSION__ : the Vera major version __VERA_MINOR__ : the Vera minor version __VERA_PATCH__ : the Vera patch level

Testbenches for Verification Intellectual Property 14-33

For example, Vera version 6.2.0 would result in the following values being returned:
__VERA_VERSION__= 6 __VERA_MINOR__ = 2 __VERA_PATCH__ = 0

The following example illustrates how to check the version information at compile time using a preprocessor define clause:
# if (__VERA_MAJOR__< 6 || (__VERA_MAJOR__== 2 && __VERA_MINOR__< 1)) # error Xyz8 requires Vera version 6.1.0 or newer # endif

and at runtime in the models constructor:


task abc_Xyz8::new() { if (__VERA_MAJOR__< 6 || (__VERA_MAJOR__== 2 && __VERA_MINOR__< 1)) { error("Xyz8 requires Vera version 6.2.0 or newer"); exit(1); } ... }

Classes and Coverage Object Declarations


Class and coverage object declarations must be conditionally compiled so that they are only defined in the program file. In other words, their declarations should have the extern specifier when used in non-program files. A simple solution is to conditionally define an EXTERN symbol, as shown in Example 14-5.

Testbenches for Verification Intellectual Property 14-34

Example 14-5 Class and Coverage Object Declarations


# ifndef INSIDE_ABC_XYZ8_VR # define EXTERN extern # endif EXTERN class abc_Xyz8 { integer id; bit [7:0] mask; abc_Xyz8_port pins; task new(abc_Xyz8_port pins); } #undef EXTERN

When the site-wide installation script compiles the Vera source code (.vr) file for the abc_Xyz8 class it must define the INSIDE_ABC_XYZ8_VR symbol:
vera -cmp -vip -DINSIDE_ABC_XYZ8_VR Xyz8.vr

Multiple Instance Support


Model classes should support multiple instances. This implies that static variables should be used with care because they are shared between all instances of a model. Multiple instances also imply multiple Vera interface declarations. To prevent the collision of interface names, the model installation script must create a separate interface header for each model instance. Example 14-6 shows a sample testbench that creates two instances of the Xyz8 model.

Testbenches for Verification Intellectual Property 14-35

Example 14-6 Supporting Multiple Instances


# define INSIDE_PROGRAM_FILE // Include class declarations for the model # include abc_Xyz8.vri // Include local files with interface declarations // Interface and binds for first instance # include abc/abc_Xyz8_ifc1.vri // Interface and binds for second instance #include abc/abc_Xyz8_ifc2.vri vera_attribute RTIME_LOAD_LIST_main = testbench.vro; program testbench { abc_Xyz8 u1 = new(abc_Xyz8_bind1); abc_Xyz8 u2 = new(abc_Xyz8_bind2); ... }

The port declarations and class declarations are included only once by the abc_Xyz8.vri file so each instance of the model is created with the same port type. Example 14-7 shows a sample interface file for the first instance:

Example 14-7 The First Instance of a Multiple Instance


# # # # # # # # # ifndef define endif ifndef define endif ifndef define endif abc_Xyz8_ifc1_VRI abc_Xyz8_ifc1_VRI abc_SAMPLE_SKEW abc_SAMPLE_SKEW #-1 abc_DRIVE_SKEW abc_DRIVE_SKEW #0

interface abc_Xyz8_ifc1 { inout [7:0] AD PSAMPLE abc_SAMPLE_SKEW PHOLD abc_DRIVE_SKEW; ... }

Testbenches for Verification Intellectual Property 14-36

bind abc_Xyz8_port abc_Xyz8_bind1 { ad abc_PREFIX_Xyz8_ifc.AD ; ... } # undef abc_SAMPLE_SKEW # undef abc_DRIVE_SKEW # endif //abc_Xyz8_ifc1_VRI

You can edit the interface file to change the skews, add hdl_node constructs, and modify the bindings.

Testbenches for Verification Intellectual Property 14-37

Testbenches for Verification Intellectual Property 14-38

Index
Symbols
!in constraint expression 5-33 set operator 5-35 +enable_solver_trace 3-37, 3-41 +enable_solver_trace_on_failure 3-37 +vera+lic+wait 3-23, 3-31 +vera_aspects 3-35 +vera_cache_dir 3-35 +vera_continue_on_error 3-30 +vera_coverage_control 3-36 +vera_debug_on_error 3-30 +vera_debug_on_int 3-30 +vera_debug_on_start 3-30, 12-17 +vera_debug_show_log 3-36 +vera_directc 3-37 +vera_disable_random_stability 3-30 +vera_dyn 3-31 +vera_enable_checker_trace 3-37 +vera_enable_checker_trace_on_failure 3-37 +vera_enable_mprint 3-31 +vera_exit_on_error 3-31 +vera_full_conflict_info 3-31 +vera_inst_path 3-38 +vera_interactive_plot 3-31, 12-14, 12-17 +vera_load 3-38 +vera_mailbox_size 3-38 +vera_main_name 3-31 +vera_mload 3-38 +vera_mload_define 3-38 +vera_no_hdl_task_semaphore 3-32 +vera_object_filename 3-38 +vera_path_sep 3-32 +vera_pload 3-39 +vera_pload_define 3-39 +vera_plot 3-39, 12-2 +vera_profile_filename 3-39, 10-4, 10-9 +vera_profile_interval 3-40 +vera_profile_limit 3-40, 10-4 +vera_profile_object 3-32, 10-12 +vera_profile_object_verbose 3-32, 10-15 +vera_profile_range 3-40 +vera_profile_sort_by_name 3-32, 10-4 +vera_profile_start 3-33 +vera_rand48_seed 3-41 +vera_random_seed 3-41 +vera_random_seed_automatic 3-33 +vera_random_v0 3-33 +vera_region_size 3-41 +vera_semaphore_size 3-41 +vera_solver_model 3-41, 3-42 +vera_stop_on_end 3-33

IN-1

+vera_stop_on_error 3-34 +vera_sysclk_err 3-34 +vera_udf 3-42 +vera_use_system_random 3-34 +vera_vros 3-42 => 5-24, 5-39

A
-alim 3-26 -ansi 3-6 ANSI mode 3-6 -aop 3-6 argument external default 3-46 array_name.size() 5-27 syntax 5-28 arrays setting maximum number of elements 3-26 assertion classes 9-2 assertion operations 9-2 assoc_size 5-29, 5-30, 6-6 syntax 6-6 attributes for methods assoc_size 6-6 big_endian 6-5 bit_normal 6-5 bit_reverse 6-5 dynamic_size 6-6 little_endian 6-4

boundary() 5-118, 5-119 post_boundary() 5-120 pre_boundary() 5-120 rand 5-119 randc 5-119 boundary() 5-120, 5-121 pre_boundary() 5-120 break usage in VSG 5-130 break and continue break 5-130 continue 5-131

C
case usage in VSG 5-128 case statements 5-128 -cfg 3-26 cleanup() 10-27 clock 13-5 clock_alias 13-6 compilation errors setting maximum number 3-19 compilation options 3-43-27 compile options general 3-2 compiler options +vera+lic+wait 3-23 -alim 3-26 -all_force 3-6 -ansi 3-6 -aop 3-6 -cfg 3-26 -D 3-9 -dep_check 3-4, 3-10 -dyn 3-10 -F 3-10 example 3-11 -f syntax 3-10

B
bad_trans not 7-51 big_endian 6-4 bin_activation 7-101 bit_normal 6-4 bit_reverse 6-4, 6-5 boundary conditions 5-1185-122

IN-2

-g 3-14 -H 3-14 -h 3-14 -HC 3-16 -HCnu 3-16 -Hnu 3-17 -hnu 3-17 -i 3-18 -i_skew 3-18 -ip 3-24 -local 3-19 -log_file 3-19 -max_error_number 3-19 -no_dep_graph 3-19 -no_warn_null 3-20 -print_deps 3-20 -q 3-22 -random_compat 3-9, 3-22 -shell 3-26 -systemc 3-23 -tdef 3-23 -timescale 3-26 -top 3-27 -top_file 3-23 -tradition 3-23 -vlog 3-27 -widen_args 3-24 -y 3-24 compiler switches -c 1-9 -get_plus_arg 10-22 -I 1-8 -print 3-3 -t 1-9 -V 3-4 -vcon 3-4 configuration file clock 13-5 clock_alias 13-6 connect 13-6 template for 13-10 timescale statement 13-3

veritask 13-9 configuration guide location of 2-4 connect 13-6 constraint block variable order solve-before 5-66 syntax 5-66 constraint blocks 5-33 inheritance 5-34 set membership 5-35 constraint blocks, external 5-34 constraint_mode() 5-25 syntax 5-101 constraints array aggregates syntax 5-49, 5-51 array_name.size() 5-27 distribution 5-36 global 5-42 if-else 5-40 implication 5-39 continue syntax 5-130, 5-131, 5-134 usage in VSG 5-131 coverag_group embedded syntax for defining 7-4 syntax for instantiating 7-8 embedded syntax for disabling 7-9 syntax for defining 7-4 coverage attributes bin_activation, restrictions on 7-76 closed-loop analysis 7-3 coverage_backup_database_file() 7-88 coverage_load() 7-89 single coverage_group 7-89 coverage_save_database() 7-88 coverage_set_database_file_name() 7-87 cross bins precedence semantics 7-58, 7-125

IN-3

cumulative 7-77 expressions interface signal bind 7-76 used for 7-75 expressions, restrictions on 7-75 get_coverage() 7-79 get_inst_coverage() 7-79 inst_query() 7-106, 7-111 example 7-111 instance names auto-naming example 7-91 user-specified names syntax 7-92 instance-based 7-77 instantiation explicit 7-8 loading coverage data coverage_instance() 7-90 loading embedded coverage data coverage_instance() 7-90 open-loop analysis 7-3 predefined function cross constructs syntax 7-97 sample constructs syntax 7-97 predefined tasks cross constructs syntax 7-97 sample constructs syntax 7-97 syntax 7-95 query() 7-93 invoked on 7-109 used to 7-106 what not used to 7-106 query_str() 7-95 syntax 7-113 temporal query() syntax 7-113

coverage declarations attribute definitions syntax 7-58, 7-125 ignored syntax 7-58, 7-124 illegal declarations m_bad_trans 7-51 not_trans 7-51 t_not_trans 7-51 illegal state declarations 7-42 bad_state 7-42 syntax 7-58, 7-124 m_bad_state 7-42 not state 7-42 multiple state bin declarations 7-41 m_state 7-38 state declarations not 7-39 transition declarations all state transition argument 7-46 conditional 7-47 m_trans 7-45 multiple transition states 7-44 not trans state specification 7-47 transition bin names 7-47 wildcard 7-48 wildcard state declarations 7-41 wildcard 7-41 coverage group attributes async 7-67 example 7-67 at_least 7-82 auto_bin_max 7-82 bin_activation 7-82, 7-101 collect 7-83 cov_comment syntax 7-83 cov_comment, restrictions on 7-76 cov_weight 7-83 coverage_goal 7-84 cross_bin_max 7-138 cross_num_print_missing 7-139

IN-4

cumulative 7-84 cumulative, restrictions on 7-76 overlap_state 7-84 overlap_state, restrictions on 7-76 overlap_trans 7-84 overlap_trans, restrictions on 7-76 coverage group atttributes bin_activation example 7-105 set_bin_activation() example 7-105 coverage_backup_database_file() 7-88 coverage_group 7-3 embedded explicit instantiation 7-8 implicit instantiation 7-11 predefined functions 7-94, 7-95, 7-96, 7-97, 7-98, 7-99, 7-100 syntax 7-93 predefined tasks 7-96 coverage_group_attributes at_least 7-78 cross_auto_bin_max 7-136 example 7-137 syntax 7-137 cross_num_print_missing 7-132 example 7-133 syntax 7-133 coverage_instance() 7-90 coverage_load 7-89 coverage_point definition 7-22 coverage_save_database() 7-88 coverage_set_database_file_name() 7-87

-y 3-24 dist 5-37 constraint expression 5-33 -dyn 3-10, 10-25 dynamic_size 5-30

E
environment variables VERA_OVERWRITE 10-21 VERA_SIMULATOR 3-25 VERA_WIDEN_ARGS 3-24 exit_status 2-6 expression distribution syntax 5-37 set syntax 5-35 external declarations 3-45

F
-F 3-10 example 3-11 -f syntax 3-10 foreach constraints 5-44 syntax 5-44 functions external default arguments 3-46 external functions 3-45

G
-g 3-14 general options -help 3-2 -pp 3-3 -print 3-3 -proj 3-3

D
-D 3-9 data packing and unpacking 6-1 property attributes 6-4 -dep_check 3-4, 3-10

IN-5

-rvm_version 3-3 -tem 3-3 -v 3-3 -vmc 3-4 get_at_least() 7-98 get_auto_bin_least() 7-94 get_auto_bin_max() 7-94, 7-95, 7-96, 7-97, 7-98, 7-99, 7-100 get_cov_weight() 7-98 get_cov_weightt() 7-94 get_coverage() 7-79 get_coverage_goal() 7-94, 7-98 get_cycle() 7-75 -get_plus_arg 10-22 get_plus_arg syntax 3-43 get_plus_arg() 3-43 get_time() 7-75 getstate() 5-9 GUI debbugger Vera 1-10

H
-H 3-14 -h 3-14 hard 5-73 -HC 3-16 -HCnu 3-16 HDL_filename.v definition of 1-9 header files 3-14 -help 3-2 -Hnu 3-17 -hnu 3-17

-i 3-18 -i_skew 3-18 if-else production definition 5-127 usage in VSG 5-127 ignored 7-58, 7-124 implication constraint syntax 5-39 in constraint expression 5-33 set operator 5-35 including files 1-8 inistate() 5-8 inst_get_at_least() 7-94, 7-99 inst_get_auto_bin_max() 7-94, 7-100 inst_get_collect() 7-94 inst_get_cov_weight() 7-94, 7-99 inst_get_coverage_goal() 7-95, 7-99 inst_query() 7-93, 7-95, 7-99 inst_set_at_least() 7-96, 7-99 inst_set_auto_bin_max() 7-96, 7-100 inst_set_bin_activation 7-95 inst_set_bin_activation() syntax 7-104 inst_set_collect() 7-96 inst_set_cov_weight() 7-97, 7-99 inst_set_coverage_goal() 7-97, 7-99 instance-specific plus arguments 13-14 interface specifications generating ASCII text files 3-18 -ip 3-24

K
keywords big_endian 6-5 bit_normal 6-5 bit_reverse 6-5 hard 5-73

I
-I 1-8, 3-17

IN-6

little_endian 6-4 packed 6-5 prod 5-132 prodget 5-134 prodset 5-133 randcase 5-12 randseq 5-123 unpacked 6-5

NO_VARS 5-120 -no_warn_null 3-20 null object handles 6-8

O
object files Vera 13-11 OK_LAST 5-120 OpernVera assertion classes 9-2 OpernVera assertion operations 9-2

L
line wrapping 3-3 little_endian 6-4 load() 7-97 -local 3-19 -log_file 3-19

P
pack() 6-6, 6-8 example 6-10 post_pack() 6-10 pre_pack() 6-10 syntax 6-7 packed 6-4 packed bit_normal, 6-5 packing and unpacking pack() 6-6 property attributes 6-4 unpack() 6-8 packing methods 6-6 attributes for big_endian 6-5 bit_normal 6-5 bit_reverse 6-5 little_endian 6-4 plus arguments plus argument requests CHECK 3-43 HNUM 3-43 NUM 3-43 STR 3-43 post_boundary() 5-120 syntax 5-121 post_pack() 6-10

M
m_state 7-38 m_trans 7-45 mailboxes setting maximum number 3-38 main-specific plus arguments 13-13 manual seeding srandom() 5-10 -max_error 3-19 -max_error_number 3-19 -mhdl 2-21 mixed HDL 2-17 SRO_MX 2-22 VCS_MX 2-21 MTI VHDL, compiling with 9-25

N
-no_dep_graph -y 3-24 -no_depth_graph 3-19

IN-7

post_randomize() 5-26 post_unpack() 6-10 -pp 3-3 -Pprinter 3-3 pre_boundary() 5-120 syntax 5-121 pre_pack() 6-10 pre_randomize() 5-26 pre_unpack() 6-10 preprocessor options -I 3-17 -print 3-3 -print_deps 3-20 -y 3-24 printing Vera files 3-3 prodget() 5-134 prodset() 5-133 production definitions 5-123 production items 5-123 weights 5-123 production weights 5-126 profiler, memory 10-7 -proj 3-3 project files #define 13-2 #include 13-2 main 13-2 property attributes

SUM 7-107 query_str() 7-95, 7-99 quiet mode 3-22

R
rand 5-27 rand modifier 5-30 rand_chi_square() 5-20 rand_erlang() 5-20 rand_mode() 5-25, 5-98 syntax 5-98 rand_normal() 5-18 rand_t() 5-19 rand48() 5-16 randc 5-27 randc modifier 5-31 randcase 5-125-13 random number generators getstate() 5-9 inistate() 5-8 rand_chi_square() 5-20 rand_erlang() 5-20 rand_exponential() 5-19 rand_normal() 5-18 rand_poisson() 5-19 rand_t() 5-19 rand48() 5-16 random() 5-14 random_range() 5-18 setstate() 5-8 srandom() 5-7 urand48() 5-16 urandom() 5-15 urandom_range() 5-17 random numbers +vera_random_v0 3-33 setting seeds at compile time 3-41 random() 5-14, 5-130 -random_compat 3-9, 3-22

Q
-q 3-22 query() 7-75, 7-95, 7-99, 7-106 query() commands COVERAGE 7-107 FIRST 7-107 GOAL 7-107 NEXT 7-107 NUM_BIN 7-107 SAMPLE 7-107

IN-8

random_compat vera_restore_rng_state() 5-12 vera_save_rng_state() 5-12 random_range() 5-18 randomize() 5-21 syntax 5-88 randomize() with 5-23 syntax 5-94 randseq 5-123, 5-125, 5-130, 5-136 syntax to define block 5-123 regions setting maximum number 3-41 repeat usage in VSG 5-129 repeat loops 5-129 random() 5-130 RTIME_LOAD_LIST 14-28 RTIME_UDF_LIST 14-16 -rvm_version 3-3

S
sample syntax 7-21 samples predefined coverage group methods 7-100 samples or crosses predefined coverage group methods 7-98 sampling events, types of clock edge syntax 7-63 general task calls example 7-66 ova events example 7-65 signal edge syntax 7-63 signal edges clock edge example 7-63 sync events

example 7-64 syntax 7-64 variable changes example 7-64 syntax 7-64 save/restart 10-19 semaphores setting maximum number 3-41 set expression 5-35 set_at_least() 7-96, 7-99 set_auto_bin_max() 7-96, 7-100 set_bin_activation 7-95 set_bin_activation() syntax 7-102 set_cov_weight() 7-96, 7-99 set_coverage_goal() 7-96, 7-99 set_name() 7-97 setstate() 5-8 -shell 3-26 shell file Vera 1-6 SHELL_MAX_CONCUR 14-19 SHELL_MAX_INST 14-19 solve 5-65 solve-before example 5-65 hard 5-73 syntax 5-66 srandom() 5-7 state not 7-39 wildcard 7-41 stream generation production definitions 5-123 stream generator randseq 5-123 subroutines declaring external 3-45 external default arguments 3-46 external definitions

IN-9

declaring external subroutines 3-45 external subroutines 3-45 surround-by-X 13-8 SystemC calling OpenVera tasks from 2-32 calling tasks from OpenVera 2-32 creating an interface 2-28 flow 2-27 running with OpenVera 2-29 -systemc 3-23 SystemClock 1-7, 13-9

all 7-46 not 7-47 wildcard 7-48

U
unpack() 6-8, 6-10 example 6-10 syntax 6-8 unpacked 6-4, 6-5 unpacking methods 6-8 attributes for big_endian 6-5 bit_normal 6-5 bit_reverse 6-5 little_endian 6-4 unpack() 6-8 urand48() 5-16 urandom() 5-15 urandom_range() 5-17

T
-t 1-9 tasks external default arguments 3-46 external tasks 3-45 -tdef 3-23 -tem 3-3 template generator 1-7 invoking 3-3 -tem 1-8 template file, blank 2-8, 2-15 template options -c 1-9 -I 1-8 -t 1-9 test_top files generating test_top files 3-27 testbench properties Vera properties vera_profile_start 3-33 text macros 3-9 timescale statement 13-3 switch 3-26 -top 3-27 -top_file 3-23 -tradition 3-23 trans 7-43, 7-50

V
-V 3-4 -v 3-3 value passing value declaration 5-132 prod 5-132 value passing functions prodget() 5-133 prodset() 5-133 randseq blocks 5-133 variables forward referencing 3-45 referencing 3-45 .vcon SystemClock 13-5 .vcon file, direct connection using 13-3 Vera project file 13-2 Vera runtime options +vera_continue_on_error 3-30

IN-10

+vera_debug_on_error 3-30 +vera_debug_on_start 3-30 +vera_stop_on_end 3-33 +vera_stop_on_error 3-34 coverage_control 3-36 enable_solver_trace 3-37, 3-41 enable_solver_trace_on_failure 3-37 vera_aspects 3-35 vera_cache_dir 3-35, 5-109 vera_coverage_control 3-36 vera_debug_on_error 3-30 vera_debug_on_int 3-30 vera_debug_show_log 3-36 vera_directc 3-37 vera_disable_final_report 3-30 vera_disable_random_stability 3-30 vera_dyn 3-31 vera_enable_checker_trace 3-37 vera_enable_checker_trace_on_failure 3-37 vera_enable_mprint 3-31 vera_exit_on_error 3-31 vera_full_conflict_info 3-31 vera_inst_path 3-38 vera_interactive_plot 3-31 vera_load 3-38 vera_mailbox_size 3-38 vera_main_name 3-31 vera_mload 3-38 vera_mload_define 3-38 vera_no_hdl_task_semaphore 3-32 vera_object_filename 3-38 vera_path_sep 3-32 vera_pload 3-39 vera_pload_define 3-39 vera_plot 3-39, 12-2 vera_profile_filename 3-39, 10-4, 10-9 vera_profile_interval 3-40 vera_profile_limit 3-40, 10-4 vera_profile_object 3-32 vera_profile_object_verbose 3-32, 10-15 vera_profile_range 3-40 vera_profile_sort_by_name 3-32, 10-4

vera_rand48_seed 3-41 vera_random_see_automatic 3-33 vera_random_seed 3-41 vera_random_v0 3-33 vera_region_size 3-41 vera_semaphore_size 3-41 vera_solver_mode 3-41, 3-42, 5-107 vera_udf 3-42 vera_use_system_random 3-34 vera_vros 3-42 Vera shell file 1-6 Vera standalone 1-10 VERA Stream Generator See VSG. vera_attribute 14-11 RTIME_LOAD_LIST 14-28 RTIME_UDF_LIST 14-16 SHELL_MAX_CONCUR 14-19 SHELL_MAX_INST 14-19 vera_cs 1-10 -vera_dbind 2-22 vera_disable_final_report 3-30 vera_enable_solver_trace syntax 5-104, 5-112, 5-113, 5-115 vera_enable_solver_trace_on_failure syntax 5-106 vera_plot() 12-2 syntax 12-2 vera_profile_sort_by_name 10-4 vera_profile_start 10-2, 10-4 vera_random_seed_automatic 3-33 vera_report_profile() 10-2, 10-8 vera_restore_rng_state() example 5-12 random_compat 5-12 syntax 5-11 vera_save_rng_state() example 5-12 random_compat 5-12 syntax 5-11

IN-11

VERA_WIDEN_ARGS 3-24 VeraDyn.vrh 10-25 vera.ini example of 10-3 veritask 13-9 vLoad() 10-26 -vlog 3-25, 3-26, 3-27 -vmc 3-4 void() example 5-69 semantics 5-70 syntax 5-69 VRO dynamic loader 10-24 VSG if-else usage 5-127 overview 5-122 prodget() 5-134 prodset() 5-133 production definitions 5-123

production weights 5-126 randseq 5-123 usage of case 5-128 usage of continue 5-131 usage of repeat 5-129 use of break 5-130 vUnLoad() 10-27 vUnloadAll() 10-27

W
-w 3-3 weights 5-126 -widen_args 3-24

Y
-y 3-24 -dep_check 3-24 -print_deps 3-24

IN-12

Das könnte Ihnen auch gefallen