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

®

Vera
User Guide
Version 6.3 September 2004

Comments?
E-mail your comments about Synopsys
documentation to vera-doc@synopsys.com
Copyright Notice and Proprietary Information
Copyright © 2004 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 reader’s 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, CSim, Design
Compiler, DesignPower, DesignWare, EPIC, Formality, HSPICE, Hypermodel, I, iN-Phase, InSpecs, in-Sync, Leda,
MAST, Meta, Meta-Software, ModelAccess, ModelTools, NanoSim, OpenVera, PathMill, Photolynx, Physical Compiler,
PowerMill, PrimeTime, RailMill, Raphael, RapidScript, Saber, SiVL, SNUG, SolvNet, Stream Driven Simulator, Superlog,
System Compiler, Testify, TetraMAX, TimeMill, TMA, VCS, Vera, and Virtual Stepper are registered trademarks of
Synopsys, Inc.
Trademarks (™)
abraCAD, abraMAP, 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, DFT Compiler, 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, HDL Advisor, HDL Compiler,
Hercules, Hercules-Explorer, Hercules-II, Hierarchical Optimization Technology, High Performance Option, HotPlace,
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, Proteus OPC, Protocol Compiler, PSMGen, 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, Taurus-Device, Taurus-Layout, Taurus-Lithography, Taurus-OPC,
Taurus-Process, Taurus-Topography, Taurus-Visual, Taurus-Workbench, 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.

Printed in the U.S.A.

Document Order Number: 37196-000 VA


Vera User Guide, v6.3

ii
Contents

What’s New in This Release . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xv


About This Guide. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xviii
Customer Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxi

1. Introduction
Overview of Testbench Development . . . . . . . . . . . . . . . . . . . . . . . 1-3
Components of a Basic Vera Verification Environment . . . . . . . . . . 1-4
SystemClock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-7
The Template Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-7
Vera Graphical Debugger. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-9
Running Vera Standalone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-10

2. Using Vera
The Vera Testbench Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-2
Verilog-based Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-3
VCS Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-6
VHDL-based Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-11

iii
VHDL Example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-12
Simulator Specific Instructions . . . . . . . . . . . . . . . . . . . . . . . 2-16
Mixed HDL-based Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-17
VCS_MX (Verilog on top) . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-17
VCS-MX (VHDL on top) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-22
SystemC-based Flow. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-25
Creating an OpenVera Interface. . . . . . . . . . . . . . . . . . . . . . 2-26
Running SystemC with OpenVera . . . . . . . . . . . . . . . . . . . . 2-27
Calling OpenVera Tasks from SystemC . . . . . . . . . . . . . . . . 2-30
Calling SystemC from OpenVera . . . . . . . . . . . . . . . . . . . . . 2-30

3. Compiling and Running Testbenches


Compiler Command Line Options . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2
General Options. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2
Compilation Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-4
Running Vera with a Simulator . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-26
Runtime Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-27
On and Off Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-28
Options Requiring User-Specified Values . . . . . . . . . . . . . . . . . 3-33
Passing Data at Runtime. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-39
Referencing Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-41
External Declaration of Subroutines . . . . . . . . . . . . . . . . . . . . . . . . 3-41

4. Vera-SystemC Transaction Level Interface


Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-2

iv
SystemC Memory Example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-3
SystemC Memory Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-3
Interface Configuration File . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-5
Using Vera to Create the TLI Infrastructure . . . . . . . . . . . . . . . . 4-7
Creating the Vera Testbench Program . . . . . . . . . . . . . . . . . . . . 4-8
Create SystemC main Program . . . . . . . . . . . . . . . . . . . . . . . . . 4-9
Compile and Run . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-10

5. Randomization in Vera
Random Stability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-2
Seeding for Randomization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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
Constraint Based Randomization . . . . . . . . . . . . . . . . . . . . . . . . . . 5-18
Random Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-24
Constraint Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-29
External Constraint Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . 5-30
Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-31
Set Membership . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-32

v
Distributions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-33
Conditional Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-35
Hierarchical Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-38
Variable Ordering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-40
Dynamic Constraint Modification . . . . . . . . . . . . . . . . . . . . . 5-43
Array Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-43
Default Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-58
Randomize Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-65
Inline Constraints Using "randomize() with" . . . . . . . . . . . . 5-66
pre_randomize() and post_randomize() . . . . . . . . . . . . . . . . 5-68
Disabling Random Variables . . . . . . . . . . . . . . . . . . . . . . . . 5-70
Disabling Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-72
Static Constraint Blocks and Random Variables . . . . . . . . . . . . 5-74
Dynamic Constraint Modification . . . . . . . . . . . . . . . . . . . . . . . . 5-74
Debugging Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-75
Solver Choice. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-77
Internal Caching. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-77
Efficient Use of Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-78
Compatibility with Vera Version 5.2 and older . . . . . . . . . . . . . . 5-79
Pre-6.0 Boundary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-82
Random Sequence Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-86
VSG Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-86
Production Declaration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-87
Production Controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-89
Weights for Randomization . . . . . . . . . . . . . . . . . . . . . . . . . 5-90
if-else Statements. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-91
case Statements. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-92
repeat Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-93

vi
break Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-94
continue Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-94
Passing Values Between Productions . . . . . . . . . . . . . . . . . . . . 5-95
Value Declaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-95
Value Passing Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-96

6. Data Packing and Unpacking


Pack and Unpack by System Functions . . . . . . . . . . . . . . . . . . . . . 6-2
Pack and Unpack by Class Methods . . . . . . . . . . . . . . . . . . . . . . . . 6-3
Identifying Data to Pack and Unpack . . . . . . . . . . . . . . . . . . . . . 6-3
Packing Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-4
Packing Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-6
Unpacking Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-8
Details of Pack and Unpack . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-9
Pack and Unpack Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-10

7. Functional Coverage
Coverage Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-2
Defining Coverage Models Using Coverage Groups . . . . . . . . . . . 7-3
Embedded Coverage Group . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-5
Instantiating Embedded Coverage Groups . . . . . . . . . . . . . 7-8
Vera Scoping Rules in Coverage Groups . . . . . . . . . . . . . . . . . 7-13
Defining Sampled Coverage Points . . . . . . . . . . . . . . . . . . . . . . 7-14
State and Transition Bins for Coverage Points . . . . . . . . . . . 7-17
Auto-Bin Creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-17
Overview of User Defined Bins for Coverage Points . . . . . . 7-22
User-defined States for Coverage Points . . . . . . . . . . . . . . . 7-27

vii
User-defined Illegal States for Coverage Points . . . . . . . . . . . . 7-34
User-defined Transitions for Coverage Points . . . . . . . . . . . 7-35
User-defined Illegal Transitions for Samples . . . . . . . . . . . . 7-42
Cross Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-43
User-defined Cross Coverage Bins . . . . . . . . . . . . . . . . . . . 7-46
Enhancements to cross coverage . . . . . . . . . . . . . . . . . . . . . . . 7-53
Saving/reporting missing cross product bins . . . . . . . . . . . . 7-54
Disabling generation of automatic cross product bins . . . . . 7-57
Sample Event. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-61
Types of Sampling Events . . . . . . . . . . . . . . . . . . . . . . . . . . 7-62
Passing Arguments to Coverage Groups. . . . . . . . . . . . . . . . . . 7-69
Expressions within Coverage Group Definitions . . . . . . . . . . . . 7-74
Cumulative and Instance-based Coverage . . . . . . . . . . . . . . . . . . . 7-76
Cumulative Coverage. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-76
Instance-based Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-76
Measuring Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-77
Coverage Attributes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-79
Coverage Group Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-81
Persistent Storage of Coverage Data and Post-processing Tools . 7-87
File Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-88
Reporting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-89
Loading Coverage Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-90
Test Merging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-93
Test Grading. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-96
Instance Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-97

viii
Predefined Coverage Group Tasks and Functions . . . . . . . . . . . . . 7-98
Activation/Deactivation: User Defined Bins . . . . . . . . . . . . . . . . . . 7-107
Coverage Feedback: query() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-113

8. Reference Verification Methodology (RVM)

9. Temporal Assertions and Expressions


Temporal Assertion Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-4
Adding OVA Objects to a Testbench . . . . . . . . . . . . . . . . . . . . . 9-4
Including the VeraOva.vrh Header File . . . . . . . . . . . . . . . . . . . 9-4
Setting Up the OVAEngine Object . . . . . . . . . . . . . . . . . . . . . . . 9-5
Controlling OVA Reporting. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-5
Resetting OVA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-6
Setting Up the OVAAssert Objects . . . . . . . . . . . . . . . . . . . . . . 9-6
Instantiating OVAAssert Objects . . . . . . . . . . . . . . . . . . . . . . . . 9-6
Controlling Evaluation Attempts. . . . . . . . . . . . . . . . . . . . . . . . . 9-8
Counting Successes and Failures . . . . . . . . . . . . . . . . . . . . . . . 9-9
Setting Up the OVAEvent Objects . . . . . . . . . . . . . . . . . . . . . . . 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

ix
New Features and the New OVAsim Flow . . . . . . . . . . . . . . . . . 9-14
-ova option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-16
New Vera-OVASIM Flow with Different Simulators . . . . . . . . . . 9-16
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-18
Task Invocation from the Simulator’s 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 and Debugging in Vera


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
Memory Profiling Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-13
Using vera_profile_object_verbose . . . . . . . . . . . . . . . . . . . 10-14
Verbose Profile Example . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-15

x
Save and Restart. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-17
Linking Vera with VCS’s Save/Restart . . . . . . . . . . . . . . . . . . . . 10-18
Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-20
Dynamic Loading of Vera Object Files . . . . . . . . . . . . . . . . . . . . . . 10-22
Creating a Vera Dynamic Executable Object (VDEO) . . . . . . . . 10-23
Loading and Unloading a VDEO File . . . . . . . . . . . . . . . . . . . . . 10-25
Loading. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-25
Unloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-25
Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-27
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-28
Vera Interactive Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-29
Compiling Vera Source Code for Debugging . . . . . . . . . . . . . . . 10-29
Launching the Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-30
Debugger Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-31
Menu Bar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-34
File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-34
Debug Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-35
Toolbars . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-41
Source Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-42

11. Vera Waveform Interface


OpenVera Plot Declaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-2
vera_plot() Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-5
vera_plot() Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-7
Supported Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-7
OpenVera Plot Control. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-9

xi
Plotting for VirSim Waveform Tool . . . . . . . . . . . . . . . . . . . . . . . . . . 11-9
Post Simulation Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-10
Interactive Simulation Mode. . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-10
Plotting for MTI-ModelSim Waveform Tool . . . . . . . . . . . . . . . . . . . 11-12
Post Simulation Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-12
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-13
Plotting for Novas-Debussy Waveform Tool. . . . . . . . . . . . . . . . . . . 11-14
Post Simulation Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-15
Interactive Simulation Mode. . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-17
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-17

12. Project-Based Testbenches


Vera Project File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-2
Vera Configuration File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-3
Timescale Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-3
Clock Statement. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-5
Clock Port. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-5
Clock Alias Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-6
Connect Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-6
Veritask Statement. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-9
Template for Vera Configuration File . . . . . . . . . . . . . . . . . . . . . 12-10
Vera Object Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-11
Project-based Configuration Simulation . . . . . . . . . . . . . . . . . . . . . 12-11
Main-Specific Plus Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . 12-13
Instance-Specific Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-14

xii
Mixed HDL Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-15

13. Testbenches for Verification Intellectual Property


Verification IP Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-2
Creating VIP Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-2
Protected VIP Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-3
Setting Up a VIP Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-3
Installing the VIP Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-4
Typical VIP Contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-5
Generated Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-7
Header Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-8
Documentation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-9
Writing a VIP Testbench . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-9
Editing the Makefile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-11
Configuring the VIP Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-11
Automated Loading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-12
Passing Properties via HDL Parameters . . . . . . . . . . . . . . . 13-15
C and HDL Testbenches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-16
VIP Implementation Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-16
C Testbenches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-17
HDL Testbenches. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-18
Command Interfaces for C and HDL Testbenches . . . . . . . . 13-19
Mixed Vera Testbenches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-21
Creating Verification IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-23
Connection to the User’s Testbench . . . . . . . . . . . . . . . . . . . . . 13-23

xiii
File Naming Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-26
Developing a VIP Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-26
Avoiding Naming Conflicts . . . . . . . . . . . . . . . . . . . . . . . . . . 13-27
Connecting to HDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-28
Automatic Object Loading . . . . . . . . . . . . . . . . . . . . . . . . . . 13-28
Including Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-30
Preventing Multiple Inclusion . . . . . . . . . . . . . . . . . . . . . . . . 13-30
VIP File Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-31
Deliverable Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-31
VIP Coding Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-32
Naming Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-32
Header File Naming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-33
Version Checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-33
Classes and Coverage Object Declarations. . . . . . . . . . . . . 13-35
Multiple Instance Support. . . . . . . . . . . . . . . . . . . . . . . . . . . 13-36

Index

xiv
Preface FIX ME!
This preface includes the following sections:

• What’s New in This Release


• About This Guide
• Customer Support

What’s New in This Release


This section describes the new features, enhancements, and
changes included in OpenVera 1.4.1 and Vera version 6.3.

For details of these new features and enhancements, see the Vera
6.3 Release Notes. A list of Vera documents, including the latest
release notes, is available through the Vera Document Navigator:

Vera Document Navigator


Enter the following command in a UNIX prompt to bring up the
Navigator:

%vera -doc

xv
Unless otherwise noted, you can find additional information regarding
these changes later in this book.

Language Enhancements
• Object finalize method
• error_mode() Enhancement
• Changes to existing support for array aggregates and array
containment in constraints.
• Default Constraints
• System Tasks for Save and Restore of a Global Random State
for Objects and Threads
• Support for External Class Method Definitions
• DirectC: Variable Length Argument List
• New Attribute for object_print()
• Coverage Point: Querying for Coverage Denominator
• Controlling Coverage Collection Globally.

Tool Enhancements
• Debugger Enhancements
• VHDL Template Generator
• New Compile Switch: -local
• New Compile Switch: -no_warn_null
• New Runtime option: vera_random_seed_automatic

xvi
• Enhancement to -dep_check -print_deps

Reference Verification Methodology Enhancements


• rvm_log performance improvement
• pre-defined atomic & scenario generators included

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

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. Click Vera Release Notes then, open Vera
Release Notes version 6.3.
The Vera Release Notes are available through the Vera Document
Navigator.

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

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

xviii
• The Synopsys Print Shop, from which you can order printed
copies of Synopsys documents, at http://docs.synopsys.com
• The Vera Installation 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
• FlexModel
• VirSim

xix
Conventions
The following conventions are used in Synopsys documentation.

Convention Description

Courier Indicates command syntax.

Courier italic 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.)

Courier bold Indicates user input—text 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]

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

Edit > Copy Indicates a path to a menu command, such as


opening the Edit menu and choosing Copy.

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

xxi
• 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.”

xxii
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. Vera’s Constraint Solver Engine is used to
automatically generate tests that mimic "real-life" stimuli with the
application of the verification engineer’s 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 Vera Testbench

DUT Vera shell interface

clock input clk CLOCK

input clk SystemClock

~ 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 particular needs.

The template generator is for DUT designed using Verilog. For VHDL
designed DUTs, see page 2-11).

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. The Template Generator
supports the Verilog flow only.

To invoke the template generator enter the following command:

vera -tem template_options HDL_filename.v

Note:
Verilog users should remember that the HDL module name
cannot start with a digit (for example, ‘2mod’ is not permitted).

Introduction
1-7
template_options:
is one or more of the following options:

Option Definition Required

-I Includes the directory in the search path no

-c Specifies the DUT clock signal no

-t Specifies the Verilog module name yes

-I path_name
adds an absolute or relative path to the search path for include
files.
-c clock_signal
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 module_name and HDL_filename
specifies the top HDL module name. The -t option is
mandatory.
where:

- module_name is the name of the top HDL module from which


the template is being generated.
- HDL_name is the HDL file from which the template is
generated.

Introduction
1-8
- The file HDL_name.v is the Verilog file containing the top level
module instantiated within the test_top.v file.
For example:
% vera -tem -t rrarb -c clk rrarb.v

where “rrarb” is the module name, and “clk” is the clock signal
name in the DUT file, “rrarb.v”.

Vera Graphical Debugger


When Vera starts the debugger, it automatically configures the
environment before launching the debugger. When you first install
Vera, you should check to make sure that your operating system is
properly configured. The Vera debugger is supported on Synopsys
qualified systems. For more information on the configuration of these
systems, go to:

http://www.synopsys.com/products/sw_platform.html

An additional way to check that the operating system is properly


configured is to run the debugger in standalone mode with the
command vdbg -sa. Before doing this, manually configure your
environment:

• when running the C shell:


source $VERA_HOME/mw/vdbg_setup.csh

• when running the K shell:


source $VERA_HOME/mw/vdbg_setup

Introduction
1-9
When the standalone debugger has started, test the menus and
open a file via the File Open dialog box. If all these steps work, you
should be ready to run a real debug session.

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 Vera
instance Shell
File
interface
filename.if.vrh
filname.v filename_shell.v
or
Vera
filename_shell.vhd Program
Template
~ clock generator
filename.vr.tmp

• Verilog-based Flow
• VHDL-based Flow

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 Installation Guide in:
$VERA_HOME/doc/install.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
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 == 8’h05;

the mismatch is incremented


vca_error:
covers all the VCA errors, as described in the OpenVera Language
Reference Manual: 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 == 8’h04; //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 Vera’s predefined


exit() task.
Do not rely on the value of the simulator’s exit status to determine
if the Vera program terminated normally. The simulator’s 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=8’hff; // drive "ff" to the design
@2 adder.out0 == 9’h1fe; // 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
Test Top File
File Temporary File
Temporary File Interface
Interface Header File
Header File

adder.test_top.v adder.vr.tmp adder.if.vrh

Rename & Edit

Vera Template

adder.vr

Vera Compile
vera -cmp -g adder.vr

Verilog Interface Shell Vera Object File

adder.vshell 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 OUTPUT_EDGE PHOLD


#define OUTPUT_SKEW #1
#define INPUT_SKEW #-1
#define 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 outp : OUT std_logic_vector(7 downto 0);
SIGNAL inp2 : IN std_logic_vector(7 downto 0);
SIGNAL inp1 : IN std_logic_vector(7 downto 0);
SIGNAL op : IN std_logic_vector(1 downto 0);
SIGNAL clk : IN std_logic;
SIGNAL rst : IN std_logic
);
END COMPONENT;

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.

There are two flows according to which HDL is on top:

• VCS-MX - Verilog is on top.


• VCS-MX - VHDL is on top.
Each of these flows is explained in the following sections.

VCS_MX (Verilog on top)


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 layer or inside a VHDL
package.
• Dynamically connecting (binding) a Vera signal to a Verilog/
VHDL signal (through signal_connect()) and driving/sampling it.
Here, we can also connect slices of the vectors and of course, the
signal can be in any layer of the mixed design.

Using Vera
2-17
Sample/drive statically connected signal. If you want to statically
connect a Vera signal to an intermediate node (a non-port signal in
the design under test, 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
Vera Testbench. Say 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
{
......
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 Verilog tasks that are defined in the top Verilog layer
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.
For example:

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

...

// Vera Program starts

Using Vera
2-19
program import_task_test()
{
int b=10;
...
veri_task_imported();
vhdl_task_imported();
...
arg_vh_task_imported(b);
...
}

Sampling/driving dynamically connected signal. Use


signal_connect() in the same way as with other simulators.

Running the Simulation.

1. Set the environments for Vera, VCS-MX and VCS:


setenv VERA_HOME <...>
set path = ($VERA_HOME/bin $path)
setenv VCS_HOME <...> /* VCS 7.0 release onwards */
set path = ($VCS_HOME/bin $path)
setenv SYNOPSYS_SIM <...>
/* Scirocco 2002.12 release onwards */
source ${SYNOPSYS_SIM}/admin/setup/environ.csh

2. Compile the Vera files:


Use the switch -vcs_mx with Vera.

% 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

3. Analyze the VHDL files:


% vhdlan vhdl_files

Using Vera
2-20
Note:
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.
4. 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 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.
- +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

Using Vera
2-21
VCS-MX (VHDL on top)
Using this type of mixed flow you can:

• Sample and drive a statically bound signal, which might reside in


any layer of the mixed design (static binding).
• Sample and drive a dynamically bound signal, which might reside
in any layer of the mixed design (dynamic binding).
• Import VHDL tasks, which are defined in a package.
You cannot import Verilog tasks.

To statically connect a Vera signal to an MHDL signal, use the


keyword hdl_node when specifying the signal connections inside the
interface. When specifying the signal path, absolute paths from the
top need to be given. The colon, : , is the HDL separator.

Consider the design shown in Figure 2-3.

Figure 2-3 Example of a Mixed Flow Design


top_vhdl (created by Vera or manually written)

dut_vhdl shell_vhdl

vlog_mod
reg veri_reg; //a register in vlog_mod

• top_vhdl is a VHDL entity, and has dut_vhdl and shell_vhdl as


components of its architecture.
• dut_vhdl has vlog_mod as one of its components,
• vlog_mod is a module written in Verilog.

Using Vera
2-22
Assume that the instance for vlog_mod is vlog_inst and the instance
for dut_vhdl is dut_inst. To access the register veri_reg, the path is
“top_vhdl: dut_inst: vlog_inst: veri_reg".

The declaration in the interface file is:

interface interface_name
{
...
inout vl_reg PSAMPLE PHOLD #1 hdl_node
"top_vhdl:dut_inst:vlog_inst:veri_reg";
...
}

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.

Running the Simulation.

1. Set the environments for Vera, VCS-MX and VCS.


setenv VERA_HOME <...>
set path = ($VERA_HOME/bin $path)
setenv VCS_HOME <...> /* VCS 7.0 release onwards */
set path = ($VCS_HOME/bin $path)
setenv SYNOPSYS_SIM <...> /* Scirocco 2002.12 onwards */
source ${SYNOPSYS_SIM}/admin/setup/environ.csh

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

Using Vera
2-23
3. Analyze all the Verilog files.
vlogan filename1.v ... filenameN.v

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

5. In order to elaborate the design, give the following command


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

where 'n' is a number between 1 and 4 (inclusive of 1 and 4).


+cli+n is optional. If you don’t use +cli+n then you should give

scs configuration_name -verilogcomp ""

Refer to the VCS-MX Reference Manual for more information on


using Verilog inside VHDL.

Note:
+cli+n enables capabilities “incrementally,” i.e., +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.

Using Vera
2-24
6. Include the vera_load=filename.vro, vera_mload=filename.vrl or
the vera_pload=filename.proj options in the vera.ini file.
7. 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 Manual for information about the


command-line options available with scsim.

Note:
Use +cli+n option judiciously, as this affects performance.

When connecting HDL signals statically or dynamically always


provide absolute path names (i.e., do not use any relative path
names).

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-25
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 (e.g., 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-26
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-27
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 module’s 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 user’s 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-28
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-29
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-30
You must then write a task matching the generated extern
declarations.

Using Vera
2-31
Using Vera
2-32
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 Definition
-help Lists valid Vera executable options
-pp Invokes the Vera preprocessor
-print Creates a PostScript file
-proj Creates Vera shell files from the project file
-rvm_version displays rvm version
-tem Invokes the Vera template generator
-v Returns the Vera compiler version
-V Prints complete version information
-vcon For multiple module support
-vmc 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 Definition
-ansi Invokes the ansi preprocessor
-aop Used to compile aspect oriented extensions
files.
-D Specifies a macro name
-dep_check Detects files with circular dependencies
-dyn Used to ensure that the VDEO has a unique
entry point defined.
-f Automates capturing file dependencies across
multiple files.
-F Automates capturing file dependencies across
multiple files.
-g Includes debugger information

Compiling and Running Testbenches


3-4
Option Definition
-h Updates .vrh file
-H Updates .vrh file
-HC Updates .vrh file and compiles .vro file
-HCnu Updates .vrh file only if there have been
changes and compiles .vro file
-hnu Updates .vrh file only if there have been
changes. Compiles
-Hnu Turns on the -H switch and updates the .vrh
file only if it has changed
-I Adds a specified path to the search path for
include files
-i Produces an ASCII interface definition
-i_skew Specifies default input skew
-local Includes local variables in auto generated
header files when it is specified in
combination with one of the header file
generation options
-max_error Sets the maximum number of errors before
compilation failure
-no_dep_graph No dependency graph generated when using
-dep_check.
-no_warn_null Disables pack warning messages for packing of
a null object
-print_deps Outputs dependencies for source files to
standard output.
-q Compiles in quiet mode, without a header
-random_compat Compiles files in pre-6.0 compatibility mode
-systemc Generates SystemC header file
-tdef Enables old typedef usage
-top Generates a VHDL test_top file
-traditional Preprocesses file.vr in non-ANSI mode
-vip Generates an IP core
-widen_args Applies assignment-style widening to
expressions passed as task/function arguments
-y Compiles all .vr files in specified directory.

Compiling and Running Testbenches


3-5
-ansi
preprocesses the Vera source code in ANSI mode.
-aop
supports Vera’s 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:
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.

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

Compiling and Running Testbenches


3-6
// 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

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

Compiling and Running Testbenches


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

The vera_aspects runtime option 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.
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.
-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-8
-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-9
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

Compiling and Running Testbenches


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

Compiling and Running Testbenches


3-11
#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
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
-letc -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
-Ietc -HC packet.vr out

Compiling and Running Testbenches


3-12
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.
- 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 // generates test.vrh file
vera -cmp test.vr // generates test.vro file

Compiling and Running Testbenches


3-13
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.
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;
}

Compiling and Running Testbenches


3-14
#endif

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

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

Compiling and Running Testbenches


3-15
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. For example:
vera -cmp -HCnu a.vr

will generate the following files


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

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

Compiling and Running Testbenches


3-16
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.
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 data_in[31:0] PSAMPLE 1
output ack[31:0] PHOLD 0
inout data_out[1:0] 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

Compiling and Running Testbenches


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

-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
autogenerated .vrh file.
-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 switch. It’s 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.

Compiling and Running Testbenches


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

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 a 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-2
vera -cmp -f file.list -dep_check -print_deps=
"file_dep_report"

Compiling and Running Testbenches


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

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

Compiling and Running Testbenches


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

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.

Compiling and Running Testbenches


3-21
-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.
-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. T
Note:
This switch should not be used for new Vera development as it
can sometimes cause compilation errors.
-tradition
Preprocesses file.vr in non-ANSI mode
-vip
generates encrypted Vera source files that can be used as IP
cores (see Testbenches for Verification Intellectual Property).

Compiling and Running Testbenches


3-22
-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.
simulator:
is one of the following:

Simulator Switch
Verilog -vlog
VHDL -mti, -sro, -nc_vhdl
SystemC -systemc

Vera Standalone -cs

Compiling and Running Testbenches


3-23
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 Definition
-alim Defines the maximum variable size for
which mirrored HDL variables will be
created.
-cfg Includes the specified .vcon file
-shell Sets the module name in the HDL shell.
-timescale Specifies a timescale
-top Generates a VHDL test_top file
-vlog 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.

Compiling and Running Testbenches


3-24
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
explicitly defines the simulation timescale inside the Vera shell
file.
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.

Compiling and Running Testbenches


3-25
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.”

Running Vera with a Simulator


This section lists the runtime options and parameters 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.

Compiling and Running Testbenches


3-26
switch_+arg
is any valid simulator or Vera switch/+argument (See “Runtime
Options” on page 3-27 for the list of +arguments).

Runtime Options
There are two types of runtime options:

• On and Off Options: parameters with a Boolean value, i.e., 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).
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:

Compiling and Running Testbenches


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

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 simulator’s
debugger is invoked. If Vera has control when the error occurs,
Vera’s 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.

Compiling and Running Testbenches


3-28
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.
vera_dyn
use this option if you intend to dynamically load a VDEO at
runtime.
vera_enable_mprint
allows you to use Vera’s main name error messaging capabilities.
vera_exit_on_error
causes the simulation to be terminated when a simulation error is
encountered.
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.

Compiling and Running Testbenches


3-29
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.
vera_main_name
yields the current main program name.
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 new’ed 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.

Compiling and Running Testbenches


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

Compiling and Running Testbenches


3-31
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.
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_text_debug
launches the text debugger when an error occurs.
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-32
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-33
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_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_solver_trace
enables a debug mode that displays diagnostics when the
randomize() method is called. See Debugging Constraints on
page 5-75 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
narrows down to the smallest set of inconsistent constraints, thus
aiding the debugging process. See Debugging Constraints on
page 5-75 for more details.
vera_inst_path
yields the shell instance path (read-only parameter).
vera_load
specifies a Vera object (.vro) file to be used with the simulation.

Compiling and Running Testbenches


3-34
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_define macro_name=value
vera_mload_define macro_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

If +vera_profile_start is included on the runtime command line


(see vera_profile_start on page 3-31), 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.

Compiling and Running Testbenches


3-35
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.”


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

Compiling and Running Testbenches


3-36
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.
+vera_profile_range=yyy:zzz

If time units are not specified by vera_profile_interval, yyy and


zzz are in simulation HDL time units

Compiling and Running Testbenches


3-37
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_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


page 3-13 of the Vera:Deprecated Features and Backward
Compatibility document.
vera_vros
specifies the names of multiple .vro files to be loaded:

Compiling and Running Testbenches


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

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.

The syntax is:

function reg get_plus_arg(CHECK | HNUM | NUM | STR,


string plus_arg);

Predefined Macros:
The valid values for plus argument requests are:
Request Action

CHECK returns 1 if the specified plus argument is present

HNUM returns a hexadecimal number attached to the


specified plus argument

NUM returns an integer attached to the specified plus


argument

STR returns a string attached to the specified plus


argument (returns a bit string type and not a string
primitive type)

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.

Compiling and Running Testbenches


3-39
Note:
get_plus_arg() can capture only 32-bits of a number from the
command line.

For example:

#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 );
}

Compiling and Running Testbenches


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

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 (i.e., 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);

Compiling and Running Testbenches


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

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-42
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 and does not change the existing flow. With
the Vera-SystemC Transaction Level Interface (TLI), Vera can
interface with SystemC at the transaction level. By bringing Vera’s
constraint randomization and coverage capability into the SystemC
environment, verification is greatly enhanced.

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

Vera Shell
Trans
Transaction Object Trans
Master
Object Clock
(write)
Generator
transaction channel

Trans
Object DUT

Vera (read) SystemC top


transaction channel

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 (e.g., 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, to be pass to SystemC


w_to = new();
r_to = new();

// 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);

Vera-SystemC Transaction Level Interface


4-8
w_to = w_chan.rx_get_t();
}

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

Vera-SystemC Transaction Level Interface


4-10
Compile SystemC source files
Solaris

%g++ -g -c -Wno-deprecated -I${SYSTEMC}/include \


-I$VERA_HOME/ include/systemc -I$VERA_HOME/lib \
-I$VERA_HOME/include/rvm_sc \
-I$VERA_HOME/include/rvm_sc/osci \
-I./include/rvm_sc/osci TO_mem_if.cpp

%g++ -g -c -Wno-deprecated -I${SYSTEMC}/include \


-I$VERA_HOME/ include/systemc -I$VERA_HOME/lib \
-I$VERA_HOME/include/rvm_sc \
-I$VERA_HOME/include/rvm_sc/osci \
-I./include/rvm_sc/osci mem_if_master.cpp

%g++ -g -c -Wno-deprecated-I${SYSTEMC}/include \
-I$VERA_HOME/ include/systemc -I$VERA_HOME/lib \
-I$VERA_HOME/include/rvm_sc \
-I$VERA_HOME/include/rvm_sc/osci \
-I./include/rvm_sc/osci Mem.cpp

%g++ -g -c -Wno-deprecated -I${SYSTEMC}/include \


-I$VERA_HOME/ include/systemc -I$VERA_HOME/lib \
-I$VERA_HOME/include/rvm_sc \
-I$VERA_HOME/include/rvm_sc/osci \
-I./include/rvm_sc/osci 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
-uspawn_tattletale_sc2vr

Run
% mem_testbench

Output
SystemC 2.0.1 --- Oct 31 2003 10:33:56

Vera-SystemC Transaction Level Interface


4-11
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
writeto_channel_rxwriteto_channel_1_rx1
writeto_channel_txwriteto_channel_1_tx1

++---------------------------------------------------------------++
|| VERA System Verifier (TM) ||
|| Version: 6.3.0 (Beta4) -- Mon Jul 26 13:28:58 2004 ||
|| 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

Vera-SystemC Transaction Level Interface


4-12
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-13
Vera-SystemC Transaction Level Interface
4-14
5
Randomization in Vera 5
This chapter covers the following topics:

• Random Stability
• Seeding for Randomization
• 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-18),
• 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, 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.

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.

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

Randomization in Vera
5-3
Program and thread stability
Random values returned from Vera system calls (e.g., random(),
urandom(), the randcase, 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.
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.

Randomization in Vera
5-4
Object Stability
The randomize() method built into every class exhibits “object
stability.” 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

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.
• Instances can be seeded at any time using the srandom()
initstate(), and setstate() system calls with an optional object
argument.

Randomization in Vera
5-5
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 object’s 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 object’s 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 thread’s RNG state using the seed (see srandom(),
initstate(), and setstate() below).

Other System Calls


Stability applies to all OpenVera language constructs and functions
that generate random values, including the randcase and the VSG,
randseq(). Randcase and randseq() use thread stability, even if they
are called from functions/tasks inside an object.

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

Randomization in Vera
5-6
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. The top-level
randomizer state is initialized with the specified seed value.

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.

Randomization in Vera
5-7
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.

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.

Randomization in Vera
5-8
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 object’s RNG using
the srandom() system call. This can be done either in a class
method, or external to the class definition:

class Packet
{
rand bit[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 object’s 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


These 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 object’s
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.

Example 5-1
#include <vera_defines.vrh>
class C
{
rand bit[8:0] v;
}

Randomization in Vera
5-11
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
}

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.

Randomization in Vera
5-12
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.

This is an example of a randcase block:

Example 5-2
randcase
{
10: i=1;
20: i=2;
50: i=3;
}

This example 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() 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-3
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-4
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 bit[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 bit [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 bit[31:0] urandom_range(bit[31:0] maxval[,


bit[31:0] minval=0]);

The function returns an unsigned value in the range


maxval..minval.

Example: val=urandom_range(7,0);

If the minval argument is omitted, the function returns a value in the


range maxval..0.

Example: 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: val=urandom_range(0,7);

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

Randomization in Vera
5-17
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

class Bus{
rand bit[15:0] addr;
rand bit[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 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-18
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-5
enum AddrType = low, mid, high;
class MyBus extends Bus{
rand AddrType type;

constraint addr_range{
(type == low ) => addr in { 0 : 15};
(type == mid ) => addr in { 16 : 127};
(type == high) => addr in {128 : 255};
}
}

Randomization in Vera
5-19
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 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, which declares additional constraints inline with the call to
randomize():

Example 5-6
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:

Randomization in Vera
5-20
• Constraints can be any OpenVera expression with variables and
constants of type bit, integer, or enumerated type.
• Constraint expressions follow Verilog syntax and semantics,
including precedence, associativity, sign extension, truncation,
and wrap-around.
• 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
bit 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-21
Example 5-7
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 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 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-22
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-8
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() 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 Vera’s 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-23
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, bit, and


enumerated type. Bit 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
object’s 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-24
Syntax

array_name.size() constraint

array_name
is the name of the array or SmartQ.

Example 5-9
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-25
Example 5-10
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-26
Example 5-11
rand bit[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-12
rand bit[7:0] x;

Randomization in Vera
5-27
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 bit or
enumerated types, and are limited to a maximum size of 8 bits, so
the maximum range for any randc variable is 0 to 255.

To understand randc, consider a 2-bit random variable y,

Example 5-13
randc bit[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: 0 3 2 1

next permutation: 2 1 3 0

next permutation: 2 0 1 3

Randomization in Vera
5-28
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-14
randc bit[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.

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.

Randomization in Vera
5-29
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).
• 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:

Randomization in Vera
5-30
// 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;
constraint c { x < 0; }
}

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

Randomization in Vera
5-31
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 { } )
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.

Randomization in Vera
5-32
value_range_list
is a comma-separated list of integers, enumerated types, bit
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.

Example 5-15
rand integer x, y, z;
constraint c1 {x in {3, 5, 9:15, 24:32, y:2*y, z};}

rand integer a, b, c;
constraint c2 {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.

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.

Randomization in Vera
5-33
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, bit
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-16
x dist {100 := 1, 200 := 2, 300 := 5}

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.

Randomization in Vera
5-34
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-17
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.

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;

Randomization in Vera
5-35
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 a set of semi-colon separated constraints. If the expression is
true, all of the constraints in the constraint set must be satisfied.
Example
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:

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

Randomization in Vera
5-36
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
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.
If-else style constraint declarations are equivalent to implications:

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

Randomization in Vera
5-37
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.

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

class A
{
rand bit[7:0] x;
}
class B
{
rand A left;
rand A right;
rand bit[7:0] x;

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


}

Randomization in Vera
5-38
B .x

.left .right

.x .x
A A

In this example, 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()). The

Randomization in Vera
5-39
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.

Variable Ordering
Vera 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-18
class B
{
rand bit s;
rand bit[31:0] d;
constraint c { s => d == 0; }
}

Randomization in Vera
5-40
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 true will be 1/2**32, which is almost never.

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

Example 5-19
class B
{
rand bit s;
rand bit[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.

The syntax to define variable order in a constraint block is:

solve variable_list before variable_list;

variable_list
is a comma-separated list of integral scalar variables or array
elements.
The following restrictions apply to variable ordering:

Randomization in Vera
5-41
• The variables can only be those declared as rand. Variables
declared as randc are disallowed.
• The variables must be integral scalar values of type integer, bit,
or enumerated type.
• A named constraint block member of a class may contain both
regular value constraints and ordering constraints. Ordering
constraints must occur at the top-level of the named constraint
block.
• 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.
• There must be no circular dependencies in the ordering, such as
solve a before b combined with solve b before a.
• 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:
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.

Randomization in Vera
5-42
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
• 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.

Array Constraints
Array constraints allow specification of templated 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.

Randomization in Vera
5-43
Syntax

foreach(name, [loop_variable | loop_variable_list])


{
...constraint_set...
}

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.
constraint_set
can be any valid code for constraints.

Example 5-20 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;
}
}
}

Randomization in Vera
5-44
Example 5-21 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-22 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-23 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-24 Two foreach loops

class E
{

rand integer x[];


rand 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-25 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]: 833
a[1]: 425
a[2]: 788
a[3]: 336
a[4]: 304
a[5]: 352
a[6]: 509
a[7]: 434
a[8]: 779
a[9]: 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);

Randomization in Vera
5-48
READY in function problem.randomize (bounds.vr, line 12, cycle 0)

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:

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, bit_xnor, contains. 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 // four dimensional array
or
*, *, loop_var1, loop_var2

loop_expression
any valid OpenVera expression.

Randomization in Vera
5-50
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-26
x+arr.sum() == 10;

contains operator
The array aggregate operator, contains has the following syntax:

array_name.contains(contains_expression) [with
loop_variable|loop_variable_list: (loop_expression)]

array_name
is the name of the array or SmartQ.
contains_expression
is any valid OpenVera expression.
aggregate_operator
is any one of the following: sum, product, logical_and, logical_or,
bit_and, bit_or, bit_xor, bit_xnor, contains. 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 *

Randomization in Vera
5-51
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 asterisk, *, which is a placeholder
- the number of loop_variables and asterisks together must
match the number of dimensions in the multi-dimensional
array.
- loop_variables and asterisks can occur in any order:
For example:
loop_var1, *, *, loop_var2 // four dimensional array
or
*, *, loop_var1, loop_var2

loop_expression
any valid OpenVera expression.
The contains 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-27
arr.contains(x+y) || (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-52
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.

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

constains_expression in { loop_exp(arr[0]), loop_exp(arr[1]),


loop_exp(arr[2]), ... }

Randomization in Vera
5-53
List of Aggregate Operators

Table 5-1
Operator Description
sum performs addition (see Table 4-1)
product performs multiplication (see Table 4-1)
logical_and performs logical AND operation (see Table 4-1)
logical_or performs logical OR operation (see Table 4-1)
bitwise_and performs bitwise AND operation (see Table 4-1)
bitwise_or performs bitwise OR operation (see Table 4-1)
bitwise_xor performs bitwise exclusive OR operation (see Table 4-1)
bitwise_xnor performs bitwise exclusive NOR operation (see Table 4-1)
contains creates a set membership (see page 5-51)

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

In the above example, the constraint expression generated is:

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

Example 5-29
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-54
In the above example, the constraint expression generated is:

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

Example 5-30 Multi-dimensional arrays


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

In the above example, 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-31 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-32 Contains operator


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

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

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

Randomization in Vera
5-55
Example 5-33 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-33, 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 - It is illegal to specify/constrain the size of the array,
over which an aggregate operator is specified, to value "0". The
runtime will generate a solver error for the same.
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.
Note on elaboration guards inside array aggreagates/
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

Randomization in Vera
5-56
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-34.

Example 5-34
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();
}

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-57
Consider a minor variation of the same example, where the
aggregate expression is guarded using an appropriate ternary
operator.

Example 5-35
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}

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.

Randomization in Vera
5-58
Example 5-36 illustrates the specification of default constraints.

Example 5-36 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 (i.e., 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.
• A default constraint block can be defined externally (i.e., 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.

Randomization in Vera
5-59
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


satsify 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 non-default constraint expression is guarded and the guard
is a state expression, the guard must evaluate to true. If the guard
contains a default variable, then the constraint expression
including the guard is treated as an unguarded constraint
expression.
• The non-default constraint should not be an ordering constraint.
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.

Randomization in Vera
5-60
Example 5-37
class C {
rand bit[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-37, the default constraint in block c1 is overriden 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-38
class C {
rand bit[3:0] x;
default constraint c1 {x >= 3; x <= 5;}
}

class D {
C c;
bit y;
constraint d1 {y => c.x > 5;}
}

program P {
D d = new();
d.c = new();
d.y = 1;
void = d.randomize();
d.y = 0;
void = d.randomize();
}

Randomization in Vera
5-61
In Example 5-38, the default constraint in block c1 is overriden 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-39
class A
{
rand bit[3:0] x;
rand bit[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();
}

Example 5-39 output

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

Randomization in Vera
5-62
Example 5-40
#include "vera_defines.vrh"
class A
{
rand bit[3:0] x;
rand bit[3:0] y;
rand bit 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, rand mode of g is ON
ret = a.randomize();
printf("Second call to randomize, rand mode of g is OFF and
the guard g evaluates to FALSE
ret = a.rand_mode(OFF , "g");
a.g = 0;
ret = a.randomize();
printf("Third call to randomize, rand mode of g is OFF and the
guard g evaluates to TRUE);
a.g = 1;
ret = a.randomize();
printf("Fourth call to randomize, constraint mode of
constraint block E is OFF
ret = a.constraint_mode(OFF, "E");
ret = a.rand_mode(OFF, "g");
ret = a.randomize();
}

Example 5-40 output:

First call to randomize, rand mode of g is ON


x = 3 y = 11 g = 0
Second call to randomize, rand mode of g is OFF and the guard g evaluates
to FALSE

Randomization in Vera
5-63
x = 9 y = 1 g = 0
Third call to randomize, rand mode of g is OFF and the guard g evaluates
to TRUE
x = 3 y = 1 g = 1
Fourth 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 has a rand variable in the
non-default constraint.

Therefore, the constraint is treated as non-guarded. Since the


constraint contains a default variable (y), it overrides the default
constraint.

In the second call to randomize, the guard is a state expression that


evaluated to FALSE. Therefore, the constraint does not override the
default constraint and consequently x + y == 10. In the third call to
randomize, the guard is a state expression that evaluated to
TRUE.Therefore, since the non-default constraint is valid, it overrides
the default constraint. In the fourth 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-41
#include "vera_defines.vrh"
class A
{
rand bit[3:0] x;
rand bit[3:0] y;
default constraint T
{
x + y == 10 ;
}
task post_randomize()
{
printf("x = %0d y = %0d
}
}
program test
{
integer ret;
A a = new;

Randomization in Vera
5-64
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
}

Output for Example 5-41

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.

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();

The randomize() is a virtual method which generates random values


for all the active random variables in the object, subject to the active
constraints.

Randomization in Vera
5-65
The randomize() method returns OK if it successfully sets all the
random variables and objects to valid values, otherwise it returns
FAIL.

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

This class definition declares three random variables, x, y, and z. To


randomize an instance of class SimpleSum, call the randomize()
method:

SimpleSum p = new;
integer success = p.randomize();
if (success == OK ) ...

Best practice: Checking results 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.

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() with constraint_block;

Randomization in Vera
5-66
class_object_name
is the name of the instantiated object.
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-43
class SimpleSum{
rand bit[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.

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.

Randomization in Vera
5-67
For instance, see the scoping example below, where the randomize()
with class is “Foo.”

Example 5-44
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.

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.

Randomization in Vera
5-68
Built-in definition for pre_randomize():

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

Built-in definition for post_randomize():

task post_randomize(){
if (super) super.post_randomize();
/* 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 new random values are computed and assigned, 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().

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.

NOTES:

Randomization in Vera
5-69
• 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-70
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 Action
ON Sets the specified variables to active so that they
are randomized on subsequent calls to the
randomize() method.
OFF Sets the specified variables to inactive so that
they are not randomized on subsequent calls to the
randomize() method.
REPORT Returns the current ON/OFF value for the specified
variable.

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

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.

Randomization in Vera
5-72
Predefined Macros:
ON, OFF, and REPORT specify the action.

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

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.
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-46
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");

Randomization in Vera
5-73
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.

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

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

Randomization in Vera
5-74
Debugging Constraints
Vera supports a debug mode that displays diagnostics when the
randomize() method is called. To enable this mode, use the runtime
option vera_enable_solver_trace.

Syntax

+vera_enable_solver_trace=[value]

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

Value Description
0 disables tracing
1 enables tracing
2 enables more verbose message in trace

If vera_enable_solver_trace is specified without an argument, the


default value is 1. If vera_enable_solver_trace is not specified, the
default is 2.

The option can, alternatively, be put in the .ini file as:

vera_enable_solver_trace=[value]

There is also the vera_enable_solver_trace_on_failure runtime


option, which is similar to the vera_enable_solver_trace option.

There are two 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-75
For example, if the constraints are:

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

Then, if +vera_enable_solver_trace_on_failure=2 is the option used,


you will get a report of just the inconsistent constraints. For example:

x == 0;
x == 5;

Syntax

+vera_enable_solver_trace_on_failure =[value]

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

Value Description
0 disables tracing
1 enables tracing
2 enables more verbose message in trace

If vera_enable_solver_trace_on_failure is specified without an


argument, the default value is 1. The default is 2, if
vera_enable_solver_trace_on_failure is not specified.

The option can, alternatively, be put in the .ini file as:

vera_enable_solver_trace_on_failure=[value]

Randomization in Vera
5-76
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-47
simv +vera_solver_mode=2 ...

The two solvers have differing performance characteristics. When the


solver mode is 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 the solver mode is set to 2, the solver does minimal
pre-processing, and analyzes the constraint in each call to
randomize().

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.

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:

Randomization in Vera
5-77
Example 5-48
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.

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 (i.e., 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.

Randomization in Vera
5-78
Example 5-49
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

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

Randomization in Vera
5-79
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 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.

Randomization in Vera
5-80
• 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-82 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 bit [31:0] dst;
PACKET_TYPE payload_format;
constraint c0
{
dst == (payload_format == CONTROL) ?
48'h0180C2000001 : void;
}
}

needs to be re-written either as:

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

or:

Randomization in Vera
5-81
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
Vera’s boundary capabilities are used to generate values that match
the upper and lower limits of a random variable’s valid value range.
This is particularly useful because many design flaws occur at
boundaries. Boundaries are generated when the system function
boundary() is called.

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.

Randomization in Vera
5-82
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
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

Randomization in Vera
5-83
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).

The boundary() method makes calls to pre_boundary() and


post_boundary() much in the same way that randomize() calls
pre_randomize() and post_randomize().

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.

Randomization in Vera
5-84
Predefined Macros:
- FIRST sets the affected random values to their first boundary
condition.
- NEXT, cycles through each subsequent boundary condition.
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.
This is an example of the boundary() system function:

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.

Randomization in Vera
5-85
Random Sequence Generation
Vera’s 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.

Vera’s 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 (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.

Randomization in Vera
5-86
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.
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.

Randomization in Vera
5-87
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 : add | dec;
middle : popf | pushf;
bottom : 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.

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


add pushf mov
dec popf mov
dec 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 */}

Randomization in Vera
5-88
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

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

Randomization in Vera
5-89
• 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;

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;

Randomization in Vera
5-90
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>;

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.

Randomization in Vera
5-91
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
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> ;

Randomization in Vera
5-92
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>;

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.

Randomization in Vera
5-93
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

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;

Randomization in Vera
5-94
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;
...
} ;

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;

Randomization in Vera
5-95
data_type
can be integer, bit, 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.

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 (bit|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, bit, string, enumerated
type, or object.

Randomization in Vera
5-96
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.
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 bit|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 (:).

Randomization in Vera
5-97
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.

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! */

Randomization in Vera
5-98
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(); }
;
}
}

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

Randomization in Vera
5-99
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-100
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 page 12-152 of the OpenVera LRM: Testbench manual
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 Bits required to pack


integer 32
reg[N-1:0] N
enum Minimum number of bits needed to
represent all the enum values
string 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 object’s 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 object’s 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 class’s 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 reg [47:0] da;
packed rand reg [47:0] sa;
packed rand reg [15:0] type;
packed rand reg [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 7
This chapter introduces Vera’s 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
• Persistent Storage of Coverage Data and Post-processing Tools
• Instance Names
• Predefined Coverage Group Tasks and Functions
• Coverage Feedback: query()

Functional Coverage
7-1
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 activity 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.

Vera further expands this basic functionality to include two analysis


mechanisms: open-loop analysis and closed-loop analysis.

Functional Coverage
7-2
• 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.
• 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.

Functional Coverage
7-3
• 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 may be contained inside of a class. 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 (page 16-2) in the OpenVera


LRM.

Example 7-1 shows a standalone coverage_group definition and its


instantiation.

Functional Coverage
7-4
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.

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 OpenVera’s object oriented paradigm,
providing an intuitive and expressive mechanism for defining the
coverage model associated with a class.

Functional Coverage
7-5
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;
}
}

Data members m_x and m_y will be sampled upon every positive
edge of the system clock.

Functional Coverage
7-6
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 s0’s 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, i.e.
// 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 task "new" 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.

Functional Coverage
7-12
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:

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

Functional Coverage
7-13
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];

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)

Functional Coverage
7-14
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 sample’s attributes, use the following syntax:

sample coverage_point
{
[state_bin_definitions]
[transition_bin_definitions]
[attribute_definitions]
}

coverage_point
is either a variable or an expression as defined above.
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 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 for more details.

Functional Coverage
7-15
attribute_definitions
You can use attributes for controlling various aspects of a sample.
The Coverage Attributes section details the attributes that can be
specified at the sample level, and their default values. You can
specify an attribute’s 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 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
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.

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.

Functional Coverage
7-16
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);
}

State and Transition Bins for Coverage Points


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.

You can either let Vera automatically create state bins for a coverage
point or explicitly define named state and/or transition bins for each
of the coverage points. Each named bin groups a set of values
(state) or a set of value transitions (trans) associated with a coverage
point.

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 for full definition) for defining the coverage point:

sample coverage_point [, coverage_point,...];

Functional Coverage
7-17
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 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
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;
}

Functional Coverage
7-18
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.

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.

Functional Coverage
7-19
Example 7-10
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-1 Automatically generated bins after the first


@(posedge CLOCK)
Sampled Variable Bin Name Hit Count
m_x S_12 1
m_y S_23 1

The Table 7-2 shows the automatically created bins (and their hit
counts) after the second “@(posedge CLOCK)”:

Table 7-2 Automatically generated bins after the second


@(posedge CLOCK)
Sampled Variable Bin Name Hit Count
m_x S_12 1
S_21 1
m_y S_23 2

Functional Coverage
7-20
TheTable 7-3 shows the automatically created bins (and their hit
counts) after third (and final) “@(posedge CLOCK)”:

Table 7-3 Automatically generated bins after the third


@(posedge CLOCK)
Sampled Variable Bin Name Hit Count
m_x S_12 1
S_21 1
S_OTHERS 1
m_y S_23 2
S_24 1

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.

In Example 7-11, coverage_group covType samples the global


variable sParam which is of the enumerated type, cellType.

Functional Coverage
7-21
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 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-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
}
}

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.

Functional Coverage
7-22
The syntax for defining explicit state and/or transition bins uses
ranges of values to define states and transitions. In Example 7-13 we
define two state bins and a transition bin for the sampled variable
port_number of coverage_group MyCov. We sample variable
port_number (assumed to be global) every time that 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 form 0 to 8 or 0 to14 transition bin t1’s hit count is
incremented.

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

Functional Coverage
7-23
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 Vera’s
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.

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 Vera’s performance. The
m_state and m_trans bin specifications do not expand beyond 4096
bins.

Functional Coverage
7-24
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(4’b11xx);

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.

All States and Not State


A special case of a state bin definition uses the all specification:

state state_bin_name (all);

Functional Coverage
7-25
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.

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 can be any valid Vera conditional statement.
Functions other than get_cycle() and get_time() cannot be called in

Functional Coverage
7-26
the conditional. When a conditional is attached to a bin definition, the
bin is only updated (i.e., 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 (i.e., its hit count is


incremented) only if the coverage point’s 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 Vera’s normal scoping rules (e.g.
involving global variables, class data members, etc.).

If a global variable or class data member is used in a condition, then


the current (i.e., 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 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 bin’s conditional, then the value of the argument at the time
when the coverage_group is instantiation is used in the evaluation of
the conditional.

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.

Functional Coverage
7-27
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.
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.

Functional Coverage
7-28
Example 7-14
state bin1 (8’b0000_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 8’b0000_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.

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.

Functional Coverage
7-29
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 State Value


s1_2 2
s1_3 3
s1_4 4

If no bin name is specified, the same example yields these bin


names and values:

State Bin Name State Value


s_2 2
s_3 3
s_4 4

Functional Coverage
7-30
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 state_bin_name (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:

s_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-31
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-4:

Table 7-4 State Expression and Implicit Bin Name


State Expression Implicit Bin Name
(5,7,9,11) s_5_7_9_11
(15:37) s_15_37
(base*10+3) s_base_10_3
(all) s_value (see above)

Conditionals in State Definitions


Conditional statements can be any valid Vera conditional statement.

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-32
Passing Arguments to Coverage Groups 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 (8’b0000_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(4’b11xx);

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-33
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-34
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-35
• a state bin name, specified in a state declaration and enclosed in
double quotes,
• 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].
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 (i.e., from one range set to another) is observed, the
monitor bin is not incremented.

Functional Coverage
7-36
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:

Transition Bin Name Transition

t1:2->4 2 to 4
t1:2->5 2 to 5
t1:3->4 3 to 4
t1:3->5 3 to 5

Functional Coverage
7-37
If no bin name is specified, the same example yields these bin
names and values:

Transition Bin Name Transition

t_s_2_3_s_4_5:2->4 2 to 4
t_s_2_3_s_4_5:2->5 2 to 5
t_s_2_3_s_4_5:3->4 3 to 4
t_s_2_3_s_4_5:3->5 3 to 5

All Trans and Not Trans


A special case for transition bins is the all transition argument:

trans trans_bin_name (all);

In this case, Vera creates and tracks a transition bin for every two-
state 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.

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.

Functional Coverage
7-38
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 Implicit Bin Name


(5 -> 7 -> 9 -> 11) t_5_7_9_11
(15:37 -> 2:5) t_15_37_2_5
([base*10, 9] -> "jmp[0-9]+") t_base_10_9_jmp0_9_
(all) t_all

Conditional
You can add conditional statements at the end of any transition
declaration. Conditional statements can be any valid Vera
conditional statement. 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
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.

Functional Coverage
7-39
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 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);

Example 7-21
wildcard trans tw(2’b0x -> 2’b1x);

The transition bin increments for transitions from:

00 -> 10
00 -> 11
01 -> 10
01 -> 11

Functional Coverage
7-40
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:

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

Functional Coverage
7-41
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 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.

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.

Functional Coverage
7-42
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.

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

Functional Coverage
7-43
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.

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

Functional Coverage
7-44
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,
s_2) for cross cc1 with hit count of 1.In general you can have several
crosses in a coverage_group definition. Example 7-23 shows
crosses cc1 and cc2 defined inside of a coverage_group.

Example 7-23
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);
}
}

Functional Coverage
7-45
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]
}

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

Functional Coverage
7-46
If the expression for the state evaluates to true, then cross
coverage bin state_name’s 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) ];

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 section details the attributes that can be
specified at the cross level, as well as their default values. You
can specify an attribute’s value as follows:
attribute_name = value_expression;

Functional Coverage
7-47
where attribute_name is the name of the attribute, and
value_expression is a Vera expression. See section
Expressions within Coverage Group Definitions 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
(i.e., 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-24
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);
}
}

The following describes Vera’s 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).

Functional Coverage
7-48
• Otherwise, every one of the user defined (non-illegal,
non-ignored) cross coverage bins (state) that match (expression
evaluates to true) are updated (i.e., 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-24 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.

If i is 45 and j is 26, then MyCrossBin is the only user-defined bin


whose expression evaluates to true. That bin’s 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.

Functional Coverage
7-49
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-25
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
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-26, an embedded coverage_group defines a cross cc1


for sampled variables m_y, m_z, and g_var1.

Functional Coverage
7-50
Example 7-26
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-26, 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.

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:

Functional Coverage
7-51
• 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-27 involves two invalid
expressions (flagged as errors by the Vera Compiler), and two valid
expressions

Example 7-27
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);
}
}

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.

Functional Coverage
7-52
In Example 7-27, 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 (e.g.,


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

Functional Coverage
7-53
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-28
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);
}

In Example 7-28, 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:

Functional Coverage
7-54
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-55
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-29
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-56
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-29, 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-29 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-57
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-30 illustrates the point.

Example 7-30
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-30,


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-58
be created (two user defined bins, and 64 auto-cross-product bins
associated with the 23 * 23 cross products of “x” and “y”—these
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-59
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-31
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-60
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
=======================================================

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.

Functional Coverage
7-61
Types of Sampling Events

Clock and Signal Edges. Coverage objects can be sampled on


clock or signal edges as per the synchronization command. When
the specified edge occurs, the object is sampled.

Syntax

sample_event = @([specified_edge] interface_signal | CLOCK);

In Example 7-32, all instances of coverage group cov1 are sampled


at the positive edge of the system clock.

Example 7-32
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-33, 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.

Functional Coverage
7-62
Example 7-33
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-34, the embedded coverage group cov1 in all instances


of the class MyClass will be sampled when the event ev1 is triggered.

Example 7-34
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 (i.e., some Vera thread performed a
trigger(ON) statement) sampling will not occur.

Functional Coverage
7-63
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 page 12-113 for description of Wait()
in the OpenVera LRM: Testbench book).

Example 7-35
sample_event = ova_object.Wait();

Where ova_object is an instance of an OVAEvent (see OVAEvent


Class on page 12-112 of the OpenVera LRM: Testbench book).

In Example 7-36, 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.

Example 7-36
class MyClass {
integer port_num;
OVAEvent portEvent;
coverage_group cov1 {
sample_event = portEvent.Wait()
sample port_number;
}
}

Functional Coverage
7-64
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-37, 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-37
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-65
Default Synchronous Behavior of Sampling Event. The default
behavior of sampling events is to sample the coverage object in a
synchronous fashion (i.e., 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 (i.e., 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-38, the embedded coverage group cov1 in all


instances of the class MyClass will be sampled immediately upon
the Vera event global_event being triggered.

Functional Coverage
7-66
Example 7-38
class MyClass
{
integer xref;
coverage_group cov1
{
sample_event = sync(global_event) async;
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-39, all
instances of the coverage group covType will be sampled upon the
posedge of the ifc.clk signal.

Example 7-39
#include "my_interface.vrh"
coverage_group covType ()
{
sample_event = @(posedge ifc.clk);
sample g_var;
}

Functional Coverage
7-67
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-40,
the embedded coverage group covType will be sampled upon every
change in value of the member variable m_e of the nesting class
object (i.e., 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-40
MyClass
{
integer m_e;
coverage_group covType
{
sample_event = wait_var(m_e);
sample m_e;
}
}
...
...
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-41, 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-68
Example 7-41
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_group’s


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-42, coverage_group MyCov defines a sampled


parameter paramVar that is sampled at every positive edge of the
system clock.

Functional Coverage
7-69
Example 7-42

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 (i.e., 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 also be used in state and transition bin conditionals. Finally,
they can be used in defining states associated with the cross of
coverage points (e.g., illegal and ignored bin specifications of
crosses).

Functional Coverage
7-70
In Example 7-43, 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.

Example 7-43
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-43, 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-71
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-44 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-72
Example 7-44
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 Example
{
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-73
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 the
Valid Expressions for Defining Cross Coverage Bins section 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-74
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-75
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 (i.e., 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-76
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 Coverage
Attributes section describes coverage_group attributes and
mechanisms for setting them.

The coverage for each coverage_group is the weighted sum of that


group’s 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 (i.e., 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-77
By default, Vera does not create automatic bins for ’X’ or ’Z’ values
of a coverage point. For example, if a coverage point is a 4 bit
bit-vector and the auto_bin_max attribute is set to 64 (default), then
by default the total number of possible bins for the coverage point is
16 (24). On the other hand, if Vera coverage is sampling the coverage
point when it has ’X’ or ’Z’ values (auto_bin_include_xz attribute of
the sample is set to ON or 1), then the total number of possible bins
for the 4 bit bit-vector is 64 (MIN(auto_bin_max attribute, 44)). Finally,
if the auto_bin_max attribute is set to 5, then the total number of
possible bins for the 4 bit bit-vector is 5.

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. The cross_bin_max attribute is used for computing the
coverage number for a cross. It specifies the maximum number of
cross coverage bins that are expected in a cross. If you set this
attribute, its value will be used as the upper-bound for the number of
possible bins in a cross.

Reporting and Querying Coverage Numbers


Testbench coverage is reported in the Vera Coverage HTML and text
reports (see the Persistent Storage of Coverage Data and
Post-processing Tools section for details). The reports also include
detailed information for each coverage group as well as the samples
and crosses of each group.

Functional Coverage
7-78
You can also query for the testbench coverage during the Vera run.
This allows you to react to the coverage statistics dynamically (e.g.,
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();

Note:
The get_inst_coverage() system function returns -1 when there
is no instance-based coverage information (i.e., the cumulative
attribute of the coverage_group has not been set to 0).

The Coverage Feedback: query() section 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 attribute’s value in the
coverage group’s definition (i.e., inside a coverage_group, sample, or
cross construct).

Syntax

attribute_name = value_expression;

Functional Coverage
7-79
where attribute_name is the name of the attribute, and
value_expression is an OpenVera expression (see Expressions
within Coverage Group Definitions for allowed expressions inside of
coverage_group definitions.) When an attribute in a
coverage_group’s 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.

• 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-45, 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-45
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);
}

Functional Coverage
7-80
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.

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. If
the number is exceeded, then Vera generates a warning and
creates a special bin that covers all remaining values. The special
state will be named s_OTHERS. 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-107 for more details about this attribute.
The value of the expression will be evaluated when the coverage
group containing the expression is first instantiated.

Functional Coverage
7-81
- 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
(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

Functional Coverage
7-82
to the enclosing coverage_group’s 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.
• coverage_goal: When specified for a coverage_group, the
attribute designates the desired coverage percentage for the
group. The default value is 90 (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 90.
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 (i.e., the attribute retains its default
value for the sample and crosses where coverage_goal is not
explicitly set).
• cross_auto_bin_max: This attribute controls the maximum
number of auto-cross-product bins created by the coverage
engine. The attribute can be set for a particular cross or for the
coverage_group as a whole (affecting all crosses of the
coverage_group). If the attribute is greater than or equal to zero,
it specifies the maximum number of automatically generated
cross product bins the Vera coverage engine will create for a
cross. Please refer to Cross Coverage Definition section for more
details.)
• 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

Functional Coverage
7-83
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.
• 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.
• 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
• auto_bin_include_xz: The auto_bin_include_xz attribute
specifies whether Vera should consider ’X’ and ’Z’ values for an
automatically binned coverage point. The default value of the
auto_bin_include_xz attribute is OFF or 0. In this case, Vera does
not create a bin for any of the ’X’ or ’Z’ values of the coverage
point. Vera functional coverage treats the coverage point as
having 2N values (where N is the number of bits for a bit-vector or
32 for an integer). If the auto_bin_include_xz attribute is set to
ON (or 1), Vera creates a bin for the ’X’ or ’Z’ values of the
coverage point. In this case, Vera functional coverage treats
bit-vector coverage points as having 4N values (where N is the
number of bits), and integer coverage points as having 232 + 1
values (-231 to 231, and ’X’).
The auto_bin_include_xz 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. Note that this attribute
only applies to coverage points that are automatically binned.

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-5 Coverage Attributes and Related Constructs


Attribute Name Type Default Defined in Defined Defined
Value coverage_group in in
sample cross
at_least integer (>=1) 1 Yes Yes Yes
auto_bin_max integer 64 Yes Yes No
collect boolean ON Yes Yes Yes
cov_weight integer (>=0) 1 Yes Yes Yes
coverage_goal integer 90 Yes Yes Yes
(0-100)

Functional Coverage
7-85
Table 7-5 Coverage Attributes and Related Constructs
Attribute Name Type Default Defined in Defined Defined
Value coverage_group in in
sample cross
cross_bin_max integer 231-1 Yes No Yes
cumulative boolean ON Yes No No
overlap_state boolean OFF Yes Yes No
overlap_trans boolean OFF Yes Yes No
auto_bin_include_xz boolean OFF Yes Yes No
bin_activation integer 1 Yes Yes Yes
cross_num_print_mis integer 0 Yes No Yes
sing
cross_auto_bin_max integer 0 Yes No Yes

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, auto_bin_max, coverage_goal, or cross_bin_max
attributes, Vera uses the largest value of each attribute for computing
cumulative coverage statistics (i.e., coverage numbers for the
coverage group). When different 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 (i.e., coverage numbers for the coverage group).

Functional Coverage
7-86
Persistent Storage of Coverage Data and
Post-processing Tools
At the end of the run, Vera writes out coverage data to a binary
database file for persistent storage. By default, the file is named:

vera_program_name.db

vera_program_name
is the name of the OpenVera program.
All coverage data for the Vera run is written to this database file. By
default, Vera writes out cumulative coverage data for each coverage
group. If the cumulative attribute of a coverage group is set to OFF
(or 0), Vera writes out coverage data for each instance of a coverage
group in addition to the coverage data for the group as a whole.
Vera’s coverage post-processing facilities can be used to report on
the coverage data saved in the database.

Vera supports a methodology where several testbench runs can be


run in parallel in regression farms. Each testbench run writes its
coverage data to a separate database file. This database file serves
as the persistent storage of coverage information for the Vera run.
Vera provides post-processing tools to view and manipulate the
coverage data across several runs. These include reporting, merging
and test grading tools. The reporting, test merging and test grading
tools operate off the coverage database files.

Subsequent Vera runs can also load coverage data from this
database if they want to accumulate incremental coverage data
building upon the results of the previous run.

Functional Coverage
7-87
File Control
By default, Vera saves the coverage database in the directory that
Vera is run in. Vera avoids overwriting existing database files by
generating unique non-clashing file names. The name of the
coverage database file can be controlled using the following system
task:

task coverage_set_database_file_name (file_name);

Vera’s functional coverage engine determines the name of the


database file, either based on the file name specified by the user, or
based on the name of the OpenVera program. If a file with that name
already exists, the existing file is made a backup by renaming it. For
example, if the coverage data is to be saved to a file called "test.db",
and a file with that name already exists, the existing file is backed up
by trying to rename it to "test_bak_1.db". If a file with that name
already exists, the existing file is renamed to "test_bak_2.db" -- and
so on. The following table explains the backup naming scheme for
our example.

File Name

test.db Database for latest testbench run.


test_bak_n.db Database for the testbench run before last
...
test_bak_2.db Database for 2nd testbench run
test_bak_1.db Database for 1st testbench run

The database backup can be disabled, forcing Vera to always


overwrite an existing coverage database file. This can be
accomplished using the following system task:

task coverage_backup_database_file (flag );

Functional Coverage
7-88
flag:
OFF for disabling database backup; ON for enabling database
backup

In order to not save the coverage data to a database file (if there is a
Verification Error for example), then use the following system task:

task coverage_save_database (flag );


flag:
OFF for disabling database backup; ON for enabling database backup

Reporting
Vera captures all the coverage data for a run in the database file. A
full set of HTML or text reports can be reported from the database
file. The Unix command for generating an HTML coverage report is:

vera -cov_report list_of_files_or_directories

list_of_files_or_directories
List of one or more Vera functional coverage database files, and/
or directories containing database files. If the list includes more
than one database file (or the directories include more than one
database file), the database files are merged before generating
the HTML report.
The above command generates the HTML reports. It writes out a
top-level HTML file named database_name.index.html and a
directory named database_name.fcov. To browse through the HTML
reports open the top-level HTML file into a browser of your choice. It
is not necessary to directly access any file in the database_name.fcov
directory.

Functional Coverage
7-89
For instance, given the coverage database file, Run1.db. After
generating the HTML report, there is a file Run1.index.html and a
directory Run1.fcov in the current directory. Open the
Run1.index.html file with a browser to view the coverage reports.

The Unix command for generating coverage reports in text format is:

vera -cov_text_report list_of_files_or_directories

list_of_files_or_directories
List of one or more Vera functional coverage database files, and/
or directories containing database files. If the list includes more
than one database file (or the directories include more than one
database file), the database files are merged before generating
the HTML report.
This command generates a single text file that includes all coverage
information stored in the coverage database. The file is called
database_name.txt. For instance if we have the coverage database
file, Run1.db. After generating the text report, you will see a file
Run1.text in the directory where the Unix command is invoked.

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.

Functional Coverage
7-90
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 syntax:

coverage_load("database_file_name");

The above command 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 syntax:

coverage_load("database_file_name","coverage_group_name");

In Example 7-46 below, there is a Vera class MyClass with an


embedded coverage object covType. Vera will find the cumulative
coverage data for the coverage group MyClass:covType in the
database file Run1.db and load it into the covType embedded
coverage group in MyClass.

Example 7-46
MyClass
{
integer m_e;
coverage_group covType
{
sample_event = wait_var(m_e);
sample m_e;
}
}
...
...
coverage_load("Run1.db", "MyClass:covType");

Functional Coverage
7-91
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 syntax:

coverage_instance.load("database_file_name");

To load the coverage data for an embedded coverage instance, use


the syntax:

class_object.cov_group_name.load("database_file_name");

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-47, 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-47
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;

Functional Coverage
7-92
Test Merging
Vera allows generation of a coverage report representing the
aggregation of two or more Vera runs.

The following is the complete syntax for the generating HTML


reports:

vera -cov_report list_of_files_or_directories[-save_db


db_filename|-save_db_only db_filename][-
output_report path_to_output]

list_of_files_or_directories
List of one or more Vera functional coverage database files, and/
or directories containing database files. If the list includes more
that one database file (or the directories include more than one
database file), the database files are merged before generating
the HTML report.
-save_db db_filename
is the new file where the merged database created by combining
individual database files is saved.
-save_db_only db_filename
is the new file where the merged database created by combining
individual database files is saved, without generating an HTML
report.
-output_report path_to_output

Target area to store the output report. If the path_to_output is an


existing directory, the top level index file for the report is
"'path_to_output'/result.index.html". If the path_to_output is not
an existing directory, the last field in the '/' separated string is
treated as the report name; the top level index file for the report
is "'path_to_output'.index.html.

Functional Coverage
7-93
This command generates an HTML report for a list of one or more
Vera functional coverage database files and/or directories that
contain database files. The merged database that is created by
combining multiple database files can also be saved.

The following is the complete command syntax for the generation of


text reports, given the enhancement for saving a database after
merging:

vera -cov_text_report list_of_files_or_directories [-save_db


db_filename|-save_db_only db_filename]
[-output_report path_to_output]

list_of_files_or_directories
List of one or more Vera functional coverage database files, and/
or directories containing database files. If the list includes more
that one database file (or the directories include more than one
database file), the database files are merged before generating
the text report.
-save_db db_filename
is the new file where the merged database created by combining
individual database files is saved.
-save_db_only db_filename
is the new file where the merged database created by combining
individual database files is saved, without generating a text report.
-output_report path_to_output

Target area to store the output report. If the path_to_output is an


existing directory, the report is generated in "'path_to_output'/
result.txt". If the path_to_output is not an existing directory, the
last field in the '/' separated string is treated as the report name;
the report is generated in "'path_to_output'.txt.

Functional Coverage
7-94
This command generates an text report for a list of one or more Vera
functional coverage database files and/or directories that contain
database files. Can also save the merged database that is created
by combining multiple database files.

Given the enhancement for saving a database after test grading,


-cov_grade grades a set of Vera functional coverage databases
specified as a list of database files and/or directories that contain
database files. This command generates a report (default HTML)
that includes the grading information. It can also save the database
associated with the minimal subset of tests selected by grading. The
following is the complete command syntax for performing coverage
test grading:

vera -cov_grade [grading_options]


[-cov_text_report]list_of_files_or_directories
[-save_db db_filename] [-output_report
path_to_output]

grading_options
-cov_target value:
Target coverage for grading (default 100%)
-instance;
Grade instance-based coverage rather than cumulative
coverage. The databases must include instance-based coverage
data.
-weighted:
Perform grading based on the coverage efficiency
(simulation time / coverage) of each database.
timeout value
Limits grading’s runtime to value seconds.

Functional Coverage
7-95
-cov_text_report
Generates a functional coverage text report (instead of the default
HTML report) that includes grading information.
list_of_files_or_directories
List of one or more Vera functional coverage database files, and/
or directories containing database files.
-save_db db_filename
is the new file where the database associated with the minimal
subset of tests that are selected by grading is saved.
-output_report
This option behaves the same way as in the -cov_report (if
generating the default HTML report) or the -cov_text_report
(when the -cov_text_report is specified).
This command grades a set of Vera functional coverage databases
specified as a list of database files and/or directories that contain
database files. This command generates a report (default HTML)
that includes the grading information. It can also save the database
associated with the minimal subset of tests selected by grading.

Test Grading
Vera can grade a set of functional coverage database files, allowing
you to determine a minimal subset of database files that achieve a
desired coverage percentage. This is particularly useful when there
are overlaps in the coverage space that is covered by each database
file (Vera run).

Functional Coverage
7-96
After computing the minimal subset of database files, Vera generates
a coverage report for the merged data of those files. If you generate
an HTML report (the default), the top level index page has a link to
the test grading page. If you generate a text report, test grading
information is printed at the end of the file.

By default, Vera uses coverage percentage as the grading metric.


Optionally, use coverage efficiency (coverage percentage per
simulation time) as the grading metric.

The Unix command for grading a set of database files is:

vera -cov_grade [grading_options] list_of_files_or_directories


[other_grading_options]

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-48, the name of the coverage instance will be cov1.


The full name is covType:cov1.

Example 7-48
coverage_group covType
{
sample_event = @(posedge CLOCK);
sample gVar;
}
...
covType cov1 = new();

Functional Coverage
7-97
In the case of an array of coverage objects, the names generated for
the coverage instances include the array index. In Example 7-49, the
coverage instances will be named covInst[0] and covInst[1].

Example 7-49
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");

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.

Functional Coverage
7-98
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-76 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]);

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.

Functional Coverage
7-99
function_name
The following table summarizes the predefined coverage group
functions and provides a brief description.
Table 7-6 Predefined Coverage Group Functions
Function Name Requires Description
Args
get_at_least() No Returns the value of the cumulative at_least
attribute for the coverage_group definition.
get_auto_bin_max() No Returns the value of the cumulative
auto_bin_max attribute for the coverage group
definition.
get_cov_weight() No Returns the value of the cumulative cov_weight
attribute for the coverage group definition.
get_coverage_goal() No Returns the value of the cumulative
coverage_goal attribute for the coverage group
definition.
get_cross_bin_max() No Returns the value of the cumulative
cross_bin_max attribute for the coverage group
definition.
inst_get_at_least() No Returns the value of the at_least attribute
for the coverage group instance.
inst_get_auto_bin_max() No Returns the value of the auto_bin_max
attribute for the coverage group instance.
inst_get_collect() No Returns the value of the collect attribute for
the coverage group instance.
inst_get_cov_weight()() No Returns the value of the cov_weight attribute
for the coverage group instance.
inst_get_coverage_goal No Returns the value of the coverage_goal
attribute for the coverage group instance.
inst_get_cross_bin_max() No Returns the value of the cross_bin_max
attribute for the coverage group instance.
inst_query() Yes Queries for coverage information related to
the coverage group instance.
inst_set_bin_activation() Yes Returns the number of bins affected by the
function.

Functional Coverage
7-100
Table 7-6 Predefined Coverage Group Functions
Function Name Requires Description
Args
set_bin_activation() Yes Returns the number of bins affected by the
function.
query() Yes Queries for coverage information related to
the coverage group as a whole (cumulative).
query_str() Yes 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-6 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);

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

Functional Coverage
7-101
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-7 Predefined Coverage Group Tasks
Task Name Argument Description
type
set_at_least() integer Sets the cumulative at_least attribute (which
is used for computing cumulative coverage
statistics).
set_auto_bin_max() integer Sets the cumulative auto_bin_max attribute
(which is used for controlling cumulative
coverage information).
set_cov_weight() integer Sets the cumulative cov_weight attribute
(which is used for computing cumulative
coverage statistics).
set_coverage_goal() integer Sets the cumulative coverage_goal attribute
(which is used for computing cumulative
coverage statistics).
set_cross_bin_max() integer Sets the cumulative cross_bin_max attribute
(which is used for computing cumulative
coverage statistics).
inst_set_at_least() integer Sets the at_least attribute for the coverage
group instance.
inst_set_auto_bin_max() integer Sets the auto_bin_max attribute for the
coverage group instance.
inst_set_collect() integer Sets the collect attribute for the coverage
group instance (turning off coverage data
collection for that instance).
inst_set_cov_weight() integer Sets the cov_weight attribute for the coverage
group instance.
inst_set_coverage_goal() integer Sets the coverage_goal attribute for the
coverage group instance.

Functional Coverage
7-102
Table 7-7 Predefined Coverage Group Tasks
Task Name Argument Description
type
inst_set_cross_bin_max() integer Sets the cross_bin_max attribute for the
coverage group instance.
load() string Loads data for the coverage group instance
from the Vera functional coverage database.
set_name() string Sets the name of the coverage group instance.

argument:
All predefined coverage group tasks require an argument. The
second column of Table 7-7 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-103
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-7 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-8 lists
the methods that can be invoked on a sample or cross.
Table 7-8 Predefined Coverage Group Methods for Samples or Crosses
Method Name Description
get_at_least() Returns the value of the cumulative at_least attribute
for a sample or cross.
get_cov_weight() Returns the value of the cumulative cov_weight attribute
for a sample or cross.
get_coverage_goal() Returns the value of the cumulative coverage_goal
attribute for a sample or cross.
inst_get_at_least() Returns the value of the at_least attribute for a sample
or cross of a coverage group instance.

Functional Coverage
7-104
Table 7-8 Predefined Coverage Group Methods for Samples or Crosses
Method Name Description
inst_get_cov_weight() Returns the value of the cov_weight attribute for a
sample or cross of a coverage group instance.
inst_get_coverage_goal() Returns the value of the coverage_goal attribute for a
sample or cross of a coverage group instance.
inst_query() Queries for coverage information related to a sample or
cross of a coverage group instance.
query() Queries for cumulative coverage information related to a
sample or cross of a coverage group.
query_str() 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.
set_at_least() Sets the cumulative at_least attribute (which is used
for computing cumulative coverage statistics).
set_cov_weight() Sets the cumulative cov_weight attribute (which is used
for computing cumulative coverage statistics).
set_coverage_goal() Sets the cumulative coverage_goal attribute (which is
used for computing cumulative coverage statistics).
inst_set_at_least() Sets the at_least attribute for the coverage group
instance.
inst_set_bin_activation() Activates/deactivates a user-defined state/transition bin
for a coverage_group instance.
inst_set_cov_weight() Sets the cov_weight attribute for the coverage group
instance.
inst_set_coverage_goal() Sets the coverage_goal attribute for the coverage group
instance.
set_bin_activation() Deactivates/activates a user-defined state/transition bin
for a coverage_group definition, as well as the instance
on which the function was invoked.

Functional Coverage
7-105
Table 7-9 lists the methods that can only be invoked on a sample
of the coverage_group construct.
Table 7-9 Predefined Coverage Group Methods for Samples Only
Method Name Description
get_auto_bin_max() Returns the value of the cumulative auto_bin_max
attribute for a sample.
inst_get_auto_bin_max() Returns the value of the auto_bin_max attribute for a
sample of coverage group instance.
set_auto_bin_max() Sets the cumulative auto_bin_max attribute (which is used
for controlling cumulative coverage information) on a
sample.
inst_set_auto_bin_max() Sets the auto_bin_max attribute for a sample of a
coverage group instance.

Table 7-10 lists the methods that can only be invoked on a cross
of the coverage_group construct.
Table 7-10 Predefined Coverage Group Methods for Crosses Only
Method Name Description

get_cross_bin_max() Returns the value of the cumulative cross_bin_max


attribute for a cross.
inst_get_cross_bin_max() Returns the value of the cross_bin_max attribute for a
cross of a coverage group instance.
set_cross_bin_max() Sets the cumulative cross_bin_max attribute (which is
used for computing cumulative coverage statistics) for a
cross.
inst_set_cross_bin_max() Sets the cross_bin_max attribute for a cross of a
coverage group instance.

The methods listed in the above three tables are a subset of


predefined methods for the coverage_group construct.

Functional Coverage
7-106
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 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."

Functional Coverage
7-107
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.

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 (e.g.,
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().

Functional Coverage
7-108
The functions follow the same invocation syntax as other pre-defined
functions (e.g., 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).
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

Functional Coverage
7-109
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.

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

Functional Coverage
7-110
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
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-50 illustrates the use of the bin_activation attribute and


the set_bin_activation() function.

Functional Coverage
7-111
Example 7-50
#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-112
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--i.e., 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-113
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 integer query(command);


function integer query(command, bin_type);
function integer query(command, bin_type,bin_pattern);
function integer 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-11
Command Function
COVERAGE Returns the current coverage number (percentage). You do not pass
any other arguments when using this command.
GOAL Returns a 1 if the coverage goal has been met (0 otherwise). You
do not pass any other arguments when using this command.
NUM_BIN Counts the number of bins of type bin_type.
SUM Sums the counters for all bins of type bin_type.
FIRST 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.
NEXT 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.
SAMPLE 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.

Functional Coverage
7-114
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-115
- 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-51
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);
}
}

Functional Coverage
7-116
...
MyClass obj1 = new;
...

For Example 7-51, 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-117
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-52
#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);

Functional Coverage
7-118
printf("MyCov.m_var bins: %0d\n",
obj1.MyCov.m_var.query(NUM_BIN));
printf("MyCov.m_var bins: %0d\n",
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-119
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 group’s coverage point (i.e.,
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 group’s 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-120
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-121
Functional Coverage
7-122
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 (i.e., 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 Description
OVAEngine 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
OVAAssert monitors and controls individual assertions and
expressions:
-affects only a specific assertion or expression
-resets and disables assertion attempts
OVAEvent synchronizes the testbench with events in OVA
-suspends a thread of the testbench

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 Affect
reset Resetting ends all attempts to match assertions and
expressions immediately and without results. New
attempts start normally with the next clock cycle.
disable Disabling ends all current attempts and prevents new
attempts from starting.
suspend Suspending a thread suspends the thread until the
object is triggered by its event.

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
VERA Testbench (*.vr)

Actions
OVAEngine
Triggers Event
Assertions File OVAEvent
(*.ova)

Actions
OVAAssert assertion1
Triggers Event
assertion1 OVAEvent

Actions
OVAAssert expression2
Triggers Event
expression2 OVAEvent

Event
OVAEvent

Results

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 object’s 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 object’s EnableCount() task. To see the current
value, call the object’s 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 OVAAssert Class on page 12-109 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 object’s 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 object’s Wait() task
or with Vera’s sync() task and the object’s 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 object’s 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 object’s memory space with the associated OVAEngine or
OVAAssert object’s 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 OVAEngine’s 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® 6.2 Installation Guide or the Vera® 6.2.8 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.1.

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

New Features and the New OVAsim Flow


A major enhancement in Vera 6.2 over Vera 6.1 is now 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 old
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 (i.e., 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®
6.2 Installation 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 -cmp -mti -ova test.vr
vlib work
vera -cmp -mti test.ova
vera -cmp -mti a.ova b.ova c.ova // compiling multiple files
vcom test.vhd test_shell.vhd
vera -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 Simulator’s Prompt


OVA system tasks can be called from the simulator’s 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 report’s 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


Status (succeeded at ...,
File and line with Full hierarchical name failed at ...,
Severity the assertion of the assertion Start time 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 Expression that failed (only with failure of check assertions)
failure message

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 -cpm -ova -vlog test.vr

3. Compile the design with the testbench


Create veriuser.so

vlib work
vlog test.v ttest_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 and Debugging in
Vera 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
• Vera Interactive Debugger

Testbench Optimization and Debugging in Vera


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 and Debugging in Vera


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 and Debugging in Vera


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 and Debugging in Vera


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


{

Testbench Optimization and Debugging in Vera


10-5
i +=b;
i *=a;
do_activity( i );
}
}

Example 10-3 Log File (vera.prof)


========================================================================

Vera Time Profiler

======================================================================
Current Simulation Time: 2050
Cycle Count: 21
Process Memory Size: 3908304
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

Testbench Optimization and Debugging in Vera


10-6
• 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.

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 of regions, semaphores and mailboxes,


• the creation and completion of contexts,
• 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 and Debugging in Vera


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 and Debugging in Vera


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 and Debugging in Vera


10-9
Profiled Data Types
Table 10-1 shows the statistics that are reported for each data type
that the Vera profiler monitors.

Table 10-1 Data Types Profiled


Data Type What is Printed in the Log File
semaphores 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.
regions 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.

Testbench Optimization and Debugging in Vera


10-10
Table 10-1 Data Types Profiled (Continued)
Data Type What is Printed in the Log File
mailboxes 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.
fork/join -the number of threads created,
-the number of threads finished,
-the number of threads remaining,
-the maximum number of threads that are running at
any given instance of time.
class objects 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

Testbench Optimization and Debugging in Vera


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


=========================================================
Current Simulation Time: 3679950 (time unit: 1s)
Cycle Count: 35000
Process Memory Size: 13488088

Semaphore/Region/Mailbox
----------------------------------------------------------
Type Max. no. of objects No. of objects
initially allocated currently used
----------------------------------------------------------
Semaphore 2048 5
----------------------------------------------------------
Region 256 10
----------------------------------------------------------
Mailbox 256 2
----------------------------------------------------------

Fork/Join
----------------------------------------------------------
Type No. threads No. threads No. threads Max. No.
created finished remaining per instant threads
----------------------------------------------------------
Fork/Join 50 48 2 35
----------------------------------------------------------

Classes
----------------------------------------------------------
Class Name #object #object #object
allocated freed not freed
----------------------------------------------------------
Packet 11167 167 11000

Testbench Optimization and Debugging in Vera


10-12
----------------------------------------------------------
dataChecker 8 8 0
----------------------------------------------------------
dataGen 8 8 0
----------------------------------------------------------
scoreboard 1 1 0
----------------------------------------------------------
Total Classes : 4
----------------------------------------------------------

The log file shown in Example 10-4 indicates that:

• 5 semaphores, 10 regions, and 2 mailboxes were used in the


simulation,
• 50 threads were created and 2 threads were incomplete at the
end of the simulation,
• the maximum number of threads running at any given instance of
simulation time was 35,
• 167 Packet objects were not freed at the end of the simulation

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

Testbench Optimization and Debugging in Vera


10-13
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 new’ed and freed, and the stack trace of the
location at which the objects were new’ed 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


• the number of objects of this class that have been new’ed 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.

Testbench Optimization and Debugging in Vera


10-14
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 (new’ed) 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 (new’ed) an array
of objects of class B.

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 = null;
Obj2 = null;
}

Testbench Optimization and Debugging in Vera


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

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

Testbench Optimization and Debugging in Vera


10-16
----------------------------------------------------------

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 new’ed.

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.

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

Testbench Optimization and Debugging in Vera


10-17
Linking Vera with VCS’s 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

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

Testbench Optimization and Debugging in Vera


10-18
Once simv executes a save task, such as $save( "savef" ), you can
use the save file (i.e., 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

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 Vera’s “hdl_task” feature. In this model, the save call is contained
in a Verilog task that Vera calls to save the simulation.

Testbench Optimization and Debugging in Vera


10-19
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.
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 Veraget_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"

Testbench Optimization and Debugging in Vera


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

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

Testbench Optimization and Debugging in Vera


10-21
{
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"

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,

Testbench Optimization and Debugging in Vera


10-22
• bringing the amount of memory needed to hold a large set of tests
under the user’s 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.

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();
}

Testbench Optimization and Debugging in Vera


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

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

Testbench Optimization and Debugging in Vera


10-24
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 (i.e., 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.

Unloading
Use the following system call to unload the VDEO:

task vUnloadAll()

Testbench Optimization and Debugging in Vera


10-25
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).

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.

Testbench Optimization and Debugging in Vera


10-26
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");


}

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

Testbench Optimization and Debugging in Vera


10-27
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
• The main program must be self-contained, that is, it may not
contain unresolved references to either variables or functions
defined in a VDEO.

Testbench Optimization and Debugging in Vera


10-28
• 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

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.

Compiling Vera Source Code for Debugging


When compiling OpenVera source code to be used with the Vera
debugger, use the -g compiler switch:

vera -cmp -g filename.vr

Testbench Optimization and Debugging in Vera


10-29
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 simulation starts and the property


vera_debug_on_start is defined
• A Vera breakpoint statement is reached
• A verification error occurs and the property
vera_debug_on_error is defined
• When using VCS, the simulation command $vera_debugger; is
issued from the cli prompt
• A Ctrl-C interrupt is issued and the property vera_debug_on_int
is defined
Once the Vera debugger comes up, online help is available through
what is called, “What’s This.” Simply click on the “What’s 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.

Testbench Optimization and Debugging in Vera


10-30
Note:
At the end of each debugger session, the debugger configuration
is automatically saved to a qdbgrc file. The fixed location for this
file is: user_home_directory/.qt/qdbgrc. When a subsequent
debugger session is launched, the configuration saved in the
qdbgrc file is used. If the file does not exist, the default debugger
configuration is used.

Debugger Overview
This section includes a brief overview of the new Vera debugger,
including terminology used throughout this section.

Figure 10-1 is a screenshot of the Vera debugger .

Testbench Optimization and Debugging in Vera


10-31
Figure 10-1 Snapshot of new debugger

The debugger display is composed of the following:

• Menu Bar - The menu bar has drop down menus that
encapsulate various debugger commands and options. To
expand a menu item, highlight it and left-click.
• Toolbar - The toolbar has icons that correspond to debugger
commands. To use a toolbar icon, highlight the icon and left-click.
• Source Window - The source window displays the Vera source
code for the active context.

Testbench Optimization and Debugging in Vera


10-32
• Project Workspace - The project workspace is a tabbed window
that shows any breakpoints that have been added using the
debugger, the call stack, and a list of all files currently being used
in the simulation. Left-click on desired tab to make that view
active.
• Local Watch Window - The local watch window displays all
variables and objects active within the active context, along with
their current values.
• Global Watch Window - The global watch window is a tabbed
window that displays user-defined expressions, variables, and
objects, regardless of the active context. Left-click on desired tab
to make that view active.
Note:
The user-defined expressions may now contain the null
keyword.
• Datatype Workspace - The datatype workspace is a tabbed
window that lists any active semaphores, regions, mailboxes, or
events, along with their current status. To change the datatype
being displayed, left-click one of the marked tabs.
• Status Bar - The status bar displays the current debugger status,
current simulation time, and current cursor line.
• Docking Bar - The docking bars are on the menu bar, toolbar,
source window, project workspace, local watch window, and
global watch window. Docking bars allow you to dock, undock,
expand, or hide the window or bar.

Testbench Optimization and Debugging in Vera


10-33
Menu Bar
The menu bar is shown in Figure 10-2.

Figure 10-2 Vera Debugger Menu Bar

File
The file commands are:

• Open - open the specified file in the source window


• Close - close the active source window file
• Quit - Exit the debugger and Vera. Exiting during a simulation
ends the simulation.

Edit. The edit commands are:

• Find - find a text string in the active source window matching the
find entry.
• Find next - find the next string in the editor window in focus.
• Goto - move the cursor to the specified line number in the active
source window and highlight that line.
• Customize - Allows you to customize toolbars and menu bars.

Testbench Optimization and Debugging in Vera


10-34
View. This menu lists the windows that can be hidden and shown:
toolbar, status bar, project workspace, local watch, global watch, and
datatype workspace windows. Check marks indicate which windows
are currently shown. Selecting the box next to the window name
toggles the hide option for that window.

Debug Commands
The debug commands are:

Step

The Step (Any Context) debug command advances the simulation to


the next executable statement. If the next statement is inside a new
context, the simulation advances inside that context. The code
associated with the new context is displayed in the source window. If
a statement waiting for an event is reached (trigger, semaphore,
region, mailbox or wait_child() call), the first statement in the next
READY context is executed.

Next

The Next debug command can only be executed in a context other


than the main program. When it is executed, the simulation is
advanced to the first statement after the subroutine call. If there are
breakpoints within the subroutine call or fork (or embedded within),
the simulation advances to the breakpoint and halts.

Testbench Optimization and Debugging in Vera


10-35
Run to cursor

When the Run to Cursor debug command is executed, the


simulation continues until the line of code at the current cursor
location is executed. The simulation stops as if a breakpoint is
reached. If there are breakpoints that are executed prior to the
current cursor location, the simulation advances to the breakpoint
and halts.

Add File/Line Breakpoint

The Add File/Line Breakpoint debug command inserts an enabled


debugger breakpoint at the current selected line. The line does not
have to be in the current context. The line where the breakpoint is
inserted is marked with a red square, which denotes an enabled
breakpoint.

Add Instance Breakpoint

The Add Instance Breakpoint debug command inserts an enabled


debugger breakpoint at the first line of a task or function. The task or
function does not have to be in the current context. Class methods
can be referenced (e.g., class_name::method_name). The line
where the breakpoint is inserted is marked with a red square, which
denotes an enabled breakpoint. If a breakpoint already exists, an
error message is displayed.

Testbench Optimization and Debugging in Vera


10-36
Add Watch

If the highlighted variable, expression, or object is invalid, the


command is not available. When the Add Watch command is
executed, the highlighted variable, expression, or object is added to
the global watch window. The value is displayed using the default
radix. If an array is selected without an array index, the entire array
is added to the watch window.

Set Value

The Set Value debug command enables users to explicitly assign a


value to a variable in the current context. The assigned value is used
by the simulation until the variable is assigned a new value from
within the code or through another set value command.

Enable Breakpoint

The Enable Breakpoint debug command enables a disabled


debugger breakpoint at the current cursor line.

Disable Breakpoint

The Delete Breakpoint debug command deletes a debugger


breakpoint at the current cursor line.

Testbench Optimization and Debugging in Vera


10-37
Stop in Vera

The Stop in Vera debug command halts the Vera simulation and
returns control back the Vera debugger.

Stop in HDL

When the Stop in HDL debug command is executed, the HDL


simulator is halted at the current simulation time and you are
returned to the HDL interactive prompt. You can use the HDL
interface to issue commands to the simulator. Vera commands are
not processed until Vera regains control of the simulation. Until then,
you cannot add breakpoints, global watch entities, or expand arrays
or classes until Vera regains control of the simulation.

Options
The Options menu allows you to set debugger preferences and fonts.

Testbench Optimization and Debugging in Vera


10-38
Preferences

• Display limit for array & list elements. This option allows you to set
the number of array elements lists in the watch windows. If more
elements exist, they are not shown in the watch windows.
• Default Radices. This option lets you set the default radix that is
used in displaying variables and expressions in the watch
windows.
• Source window tab size. This option allows you to define the
number of spaces that are inserted when a tab character is used.

Testbench Optimization and Debugging in Vera


10-39
Fonts

Windows
The window commands are:

• Cascade - Cascades open source windows within the main


debugger window.
• Tile - Tiles open sources windows into vertical panes.
• Tile Horizontally - Tiles the open sources windows into horizontal
panes.
• File list - Lists the open files. Selecting a file from the file list
brings it to the display front

Testbench Optimization and Debugging in Vera


10-40
Help
The help commands are:

• About. Displays the release version and release date of the Vera
debugger.
• What’s This. Context sensitive help. Select What’s This and then
point to the button or window for detailed help instructions.

Toolbars
The Vera debugger uses two toolbars which controls file and
simulation options. The toolbars can be undocked and moved, using
the docking bar at the left of the toolbar. The toolbars can be resized
once they are undocked. Figure 10-3 shows the file and debugger
toolbars:

Figure 10-3 Debugger Toolbars

The file toolbar contains 4 icons: what’s this, file open, file close, and
exit. The what’s this icon provides direct access to context sensitive
help. The file open and close features enable the opening and
closing of source files. The exit button exits the debugger and
simulation.

The debug command toolbar contains icons for the following debug
commands:

• Step
• Next
• Continue

Testbench Optimization and Debugging in Vera


10-41
• Run to cursor
• Add File/Line breakpoint
• Add instance breakpoint
• Add watch
• Set Value
• Enable breakpoint
• Enable breakpoint
• Disable breakpoint
• Remove breakpoint
• Stop in Vera
• Stop in HDL

Source Window
The source window displays the source code for the active context.
You can manually open files using the open file menu command.
Opened files are displayed in the source window. Files opened by
double-clicking on the filename in the project workspace files tab are
opened in the source window.

Testbench Optimization and Debugging in Vera


10-42
Clicking the X icon in the upper right corner of the window closes the
source window. Clicking the box icon maximizes the source window
such that it occupies all available space inside the main debugger
window (it does not cover up docked windows or toolbars, but it does
cover up other open source windows). Clicking the line icon
minimizes the source window. Minimized windows are shown as
window banners with the name of the file. When the source window
is not maximized, it floats inside the main debugger window. The
source window cannot float outside the main debugger window. You
can move the source window by clicking the banner and dragging.

Testbench Optimization and Debugging in Vera


10-43
All source code text is displayed in black. The current select line is
highlighted in light blue and the current location in the simulation is
marked with a dark blue highlight on the line number. Breakpoints
are highlighted in red. Disabled breakpoints are indicated in green.

Source Window Commands


Insert Breakpoint -Available when the cursor is at a line without a
breakpoint, this command inserts a debugger breakpoint at the
current cursor line. This can be enabled either via a context sensitive
menu (right mouse click), the debugger toolbar, or the debugger
menu.

Remove Breakpoint - This command deletes all breakpoints at the


current cursor line. This can be enabled either via a context sensitive
menu (right mouse click), the debugger toolbar, or the debugger
menu.

Enable Breakpoint - This command enables all breakpoints at the


current cursor line. This can be enabled either via a context sensitive
menu (right mouse click), the debugger toolbar, or the debugger
menu.

Disable Breakpoint - This command disables all breakpoints at the


current cursor line. This can be enabled via a context sensitive menu
(right mouse click), the debugger toolbar, or the debugger menu.

Run to Cursor - This command continues the simulation up to the


current cursor line. This can be enabled either via a context sensitive
menu (right mouse click), the debugger toolbar, or the debugger
menu.

Testbench Optimization and Debugging in Vera


10-44
Add Watch - Available after a valid variable, expression, or object is
highlighted in the source window, this command adds the highlighted
entity to the global watch window. This can be enabled either via a
context sensitive menu (right mouse click), the debugger toolbar, or
the debugger menu.

Testbench Optimization and Debugging in Vera


10-45
Testbench Optimization and Debugging in Vera
10-46
11
Vera Waveform Interface 11
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


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


11-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 Waveform Format of Generated File


VIRSIM vpd, VCD+
DEBUSSY FSDB
MTI 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.
size_limit

Vera Waveform Interface


11-3
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 Description
0 displays variables matching the exact name specified in
the variable argument.
1 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


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


11-5
Example 11-4 Plotting associative arrays of integers
vera_plot("plot",VIRSIM, ".*",1, "dump=assoc_array, integer");

Example 11-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 11-6 Plotting associative arrays of bits that are not class members
vera_plot("plot", VIRSIM, ".*",1, "dump=class,assoc_array,
reg");

Example 11-7 Plotting all OpenVera global variables and interface signals
vera_plot("vera",VIRSIM, ".*", 1);

Example 11-8 Plotting the variable or interface signals with the name
IFC_clk;
vera_plot("vera_ifc", VIRSIM, "IFC_clk", 0);

Example 11-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 (i.e., properties of any subclasses are ignored).

vera_plot("vera_var", VIRSIM, "pkt_array", 0);

Vera Waveform Interface


11-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 (i.e., local variables).

Supported Data Types


Table 11-1 lists the data types supported by VirSim, Debussy, and
MTI.

Table 11-1 Data Types Supported by VirSim, Debussy and MTI


Data Types VirSim Debussy MTI

integer Yes Yes Yes


reg/bit Yes Yes Yes
bit-vector Yes Yes Yes
enum Yes Yes Yes
port Yes Yes Yes
class object Yes Yes Yes
static members in class objects Yes Yes no
Single dimensional arrays:

Vera Waveform Interface


11-7
Table 11-1 Data Types Supported by VirSim, Debussy and MTI
Data Types VirSim Debussy MTI

integer Yes Yes No


reg/ bit Yes Yes No
bit-vector Yes Yes No
enum Yes Yes Yes
port Yes Yes Yes
class Yes Yes Yes
Multi-dimensional arrays:
integer Yes Yes No
reg/bit Yes Yes No
bit-vector Yes Yes No
enum Yes Yes Yes
port Yes Yes Yes
class Yes Yes Yes
Associative arrays:
integer Yes Yes Yes
reg/ bit Yes Yes Yes
bit-vector Yes Yes Yes
enum Yes Yes Yes
port Yes Yes Yes
class Yes Yes Yes

Vera Waveform Interface


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

Vera Waveform Interface


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

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.

Vera Waveform Interface


11-10
To plot from Vera to VirSim, add the following to your OpenVera code:

vera_plot("some_file", VIRSIM, ".*", 1);

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

Vera Waveform Interface


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

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 (e.g. 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"

Vera Waveform Interface


11-12
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.
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;

Vera Waveform Interface


11-13
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_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.

Vera Waveform Interface


11-14
• 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

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

Vera Waveform Interface


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

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.

Vera Waveform Interface


11-16
• 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.

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

Vera Waveform Interface


11-17
• Associative arrays are displayed having a scope for each
associative array with the element index attached with an
underscore.
Example:

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


11-18
12
Project-Based Testbenches 12
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 12-2)
• a configuration file (.vcon) for each Vera main program (see “Vera
Configuration File” on page 12-3)
• all relevant Vera object files (.vro) (see “Vera Object Files” on
page 12-11)

Project-Based Testbenches
12-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
12-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 file’s signal connection specifications override the


specifications in the Vera program’s interface declarations.

Vera loads the .vcon file and runs it through the preprocessor.
Preprocessor definitions (e.g., #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
12-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
12-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 12-6), the generated Vera shell file
includes an input port for that clock signal.

Project-Based Testbenches
12-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
12-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
12-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
12-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
12-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:

Project-Based Testbenches
12-10
vera -cmp -verilog -vcon test.vr new_test

generates the filenew_test.vcon.

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.

Project-Based Testbenches
12-11
4. Create an overall project file that contains information on all
modules necessary for the simulation.
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
12-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 12-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
12-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 12-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
12-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
12-15
Project-Based Testbenches
12-16
13
Testbenches for Verification Intellectual
Property 13
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


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


13-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 13-3 on page 13-7).
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 13-12).

Testbenches for Verification Intellectual Property


13-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 model’s 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 13-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


13-4
Figure 13-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 13-2 shows a typical installation tree for a VIP package.

Testbenches for Verification Intellectual Property


13-5
Figure 13-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 13-12).

Figure 13-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).

Testbenches for Verification Intellectual Property


13-6
Figure 13-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.

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.

Testbenches for Verification Intellectual Property


13-7
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 model’s VRO and DirectC libraries
using the vendor’s environment variables (see “Automated
Loading” on page 13-12).
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.
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.

Testbenches for Verification Intellectual Property


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

Figure 13-4 shows a possible SOC configuration. Each verification


model is a separate class object created and controlled by the
testbench.

Testbenches for Verification Intellectual Property


13-9
Figure 13-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.

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.

Testbenches for Verification Intellectual Property


13-10
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 model’s
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.

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.

Testbenches for Verification Intellectual Property


13-11
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 vendor’s 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";


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

Testbenches for Verification Intellectual Property


13-12
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 model’s .vri file;
in this example, abc_Xyz8.vri.

Testbenches for Verification Intellectual Property


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


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


13-15
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 model’s 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 13-12 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


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


13-17
Figure 13-5 shows a possible SOC configuration for a C testbench.

Figure 13-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 13-6 shows a possible
SOC configuration for an HDL testbench.

Testbenches for Verification Intellectual Property


13-18
Figure 13-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


13-19
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 3 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


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


13-21
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 13-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 13-7 A Mixed Vera Testbench

Testbenches for Verification Intellectual Property


13-22
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 User’s 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 user’s
testbench.

There are two ways to connect the user’s environment to the VIP
creator’s environment:

1. vshell port connection


The Vera shell is instantiated at the top level of the user’s test
environment and the user must create an instance of the shell
and “wire” all the connections.

Testbenches for Verification Intellectual Property


13-23
This method is a flexible solution for both connecting to the user’s
HDL and to the user’s 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 creator’s verification
environment.

vera_shell vshell(

// User’s 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


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


13-25
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 user’s 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 13-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


13-26
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
user’s verification environment (see “Naming Conventions” on
page 13-32).

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


13-27
For the CPU model, all class, interface, port, and binding names
must be modified:

class CPU ==> class creator_name_CPU


interface cpu ==> interface creator_name_cpu
port cpu_bus_arb ==> port creator_name_cpu_bus_arb
bind cpu_arb0 ==> bind creator_name_cpu_arb0
bind cpu_arb1 ==> 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 user’s 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 13-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


13-28
Automatic loading should be handled within a header file included by
the user’s 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


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


13-30
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 user’s 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


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


13-32
• 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


13-33
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 (i.e., 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


13-34
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 model’s 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 13-5.

Testbenches for Verification Intellectual Property


13-35
Example 13-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 13-6 shows a sample testbench that creates two instances
of the Xyz8 model.

Testbenches for Verification Intellectual Property


13-36
Example 13-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 13-7 shows a sample interface file for the first instance:

Example 13-7 The First Instance of a Multiple Instance


# ifndef abc_Xyz8_ifc1_VRI
# define abc_Xyz8_ifc1_VRI
# endif
# ifndef abc_SAMPLE_SKEW
# define abc_SAMPLE_SKEW #-1
# endif
# ifndef abc_DRIVE_SKEW
# define abc_DRIVE_SKEW #0
# endif

interface abc_Xyz8_ifc1 {
inout [7:0] AD PSAMPLE abc_SAMPLE_SKEW PHOLD abc_DRIVE_SKEW;
...
}

Testbenches for Verification Intellectual Property


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


13-38
Index

Symbols +vera_mload_define 3-35


+vera_no_hdl_task_semaphore 3-30
!in
constraint expression 5-30 +vera_object_filename 3-35
set operator 5-32 +vera_path_sep 3-30
+enable_solver_trace 3-34 +vera_pload 3-36
+enable_solver_trace_on_failure 3-34 +vera_pload_define 3-36
+vera+lic+wait 3-30 +vera_plot 3-36, 11-2
+vera_aspects 3-33 +vera_profile_filename 3-36, 10-4, 10-9
+vera_cache_dir 3-33 +vera_profile_interval 3-36
+vera_continue_on_error 3-28 +vera_profile_limit 3-37, 10-4
+vera_coverage_control 3-34 +vera_profile_object 3-30, 10-12
+vera_debug_on_error 3-28 +vera_profile_object_verbose 3-30, 10-14
+vera_debug_on_int 3-28 +vera_profile_range 3-37
+vera_debug_on_start 3-29, 11-17 +vera_profile_sort_by_name 3-31, 10-4
+vera_directc 3-34 +vera_profile_start 3-31
+vera_disable_random_stability 3-29 +vera_rand48_seed 3-38
+vera_dyn 3-29 +vera_random_seed 3-38
+vera_enable_mprint 3-29 +vera_random_seed_automatic 3-31
+vera_exit_on_error 3-29 +vera_random_v0 3-31
+vera_full_conflict_info 3-29 +vera_region_size 3-38
+vera_inst_path 3-34 +vera_semaphore_size 3-38
+vera_interactive_plot 3-29, 11-14, 11-17 +vera_solver_model 3-38
+vera_load 3-34 +vera_stop_on_end 3-32
+vera_mailbox_size 3-35 +vera_stop_on_error 3-32
+vera_main_name 3-30 +vera_text_debug 3-32
+vera_mload 3-35 +vera_use_system_random 3-32

IN-1
+vera_vros 3-38 randc 5-83
=> 5-21, 5-35, 5-36 boundary() 5-84
pre_boundary() 5-84
break
A usage in VSG 5-94
-alim 3-24 break and continue
-ansi 3-6 break 5-94
ANSI mode 3-6 continue 5-94
-aop 3-6
argument
external default 3-42
C
case
array_name.size() 5-24
usage in VSG 5-92
syntax 5-25
case statements 5-92
arrays
setting maximum number of elements 3-24 -cfg 3-25
assertion classes 9-2 cleanup() 10-26
assertion operations 9-2 clock 12-5
assoc_size 5-26, 5-27, 6-6 clock_alias 12-6
syntax 6-6 compilation errors
attributes for methods setting maximum number 3-18
assoc_size 6-6 compilation options 3-4–3-26
big_endian 6-5 compile options
bit_normal 6-5 general 3-2
bit_reverse 6-5 compiler options
dynamic_size 6-6 -alim 3-24
little_endian 6-4 -ansi 3-6
-aop 3-6
-cfg 3-25
B -D 3-8
bad_trans -dep_check 3-4, 3-9
not 7-42 -dyn 3-9
big_endian 6-4 -F 3-9
bin_activation 7-108 example 3-10
-f
bit_normal 6-4
syntax 3-9
bit_reverse 6-4, 6-5 -g 3-13
boundary conditions 5-82–5-85 -H 3-13
boundary() 5-82, 5-83 -h 3-13
post_boundary() 5-84 -HC 3-15
pre_boundary() 5-84 -HCnu 3-16
rand 5-83 -Hnu 3-16

IN-2
-hnu 3-16 constraint blocks, external 5-30
-i 3-17 constraint_mode() 5-22
-i_skew 3-17 syntax 5-72
-ip 3-22 constraints
-local 3-18 array aggregates
-max_error_number 3-18 syntax 5-49
-no_dep_graph 3-18 array_name.size() 5-24
-no_warn_null 3-19 default 5-58
-print_deps 3-19 distribution 5-33
-q 3-21 global 5-38
-random_compat 3-22 if-else 5-37
-shell 3-25 implication 5-35
-systemc 3-22 continue
-tdef 3-22 syntax 5-94, 5-97
-timescale 3-25 usage in VSG 5-94
-top 3-26 -cov_report 7-89
-tradition 3-22 coverag_group
-vlog 3-26 embedded
-widen_args 3-23 syntax for defining 7-4
-y 3-23 syntax for instantiating 7-8
compiler switches embedded syntax for disabling 7-9
-c 1-8 syntax for defining 7-4
-get_plus_arg 10-20 coverage
-I 1-8 attributes
-print 3-3 bin_activation, restrictions on 7-75
-t 1-8 closed-loop analysis 7-3
-V 3-4 coverage test grading
-vcon 3-4 syntax 7-95
configuration file coverage_backup_database_file() 7-88
clock 12-5 coverage_load() 7-91
clock_alias 12-6 single coverage_group 7-91
connect 12-6 coverage_save_database() 7-89
template for 12-10 coverage_set_database_file_name() 7-88
timescale statement 12-3 cross bins
veritask 12-9 precedence semantics 7-48
connect 12-6 cumulative 7-76
constraint block expressions
variable order interface signal
syntax 5-41 bind 7-75
constraint blocks 5-29 used for 7-74
inheritance 5-31 expressions, restrictions on 7-74
generating HTML report
set membership 5-32

IN-3
syntax 7-93 coverage declarations
get_coverage() 7-79 attribute definitions
get_inst_coverage() 7-79 syntax 7-47
grading set of database files ignored
unix command 7-97 syntax 7-47
inst_query() 7-113, 7-118 illegal declarations
example 7-118 m_bad_trans 7-43
instance names not_trans 7-42, 7-43
auto-naming t_not_trans 7-42
example 7-97 illegal state declarations 7-34
user-specified names bad_state 7-34
syntax 7-98 syntax 7-47
instance-based 7-76 m_bad_state 7-34
instantiation not state 7-34
explicit 7-8 multiple state bin declarations 7-33
loading coverage data m_state 7-29
coverage_instance() 7-92 state declarations
loading embedded coverage data not 7-31
coverage_instance() 7-92 transition declarations
open-loop analysis 7-3 all state transition argument 7-38
predefined function conditional 7-39
cross constructs m_trans 7-37
syntax 7-103 multiple transition states 7-36
sample constructs not trans state specification 7-38
syntax 7-103 transition bin names 7-39
predefined tasks wildcard 7-40
cross constructs wildcard state declarations 7-33
syntax 7-103
wildcard 7-33
sample constructs
coverage group attributes
syntax 7-103
async 7-66
syntax 7-101
example 7-66
query() 7-99
at_least 7-81
invoked on 7-116
auto_bin_max 7-81
used to 7-113
bin_activation 7-81, 7-108
what not used to 7-113
collect 7-82
query_str() 7-101
cov_comment
syntax 7-120 syntax 7-82
reporting
cov_comment, restrictions on 7-75
-cov_report 7-89
cov_weight 7-82
cov_text_report 7-90
coverage_goal 7-83
temporal
cross_auto_bin_max 7-83
query()
syntax 7-120 cross_bin_max 7-83

IN-4
cross_num_print_missing 7-84 data packing and unpacking 6-1
cumulative 7-84 property attributes 6-4
cumulative, restrictions on 7-75 -dep_check 3-4, 3-9
overlap_state 7-84 -y 3-23
overlap_state, restrictions on 7-75 dist 5-34
overlap_trans 7-84, 7-85 constraint expression 5-30
overlap_trans, restrictions on 7-75 -dyn 3-9, 10-24
coverage group atttributes dynamic_size 5-27
bin_activation
example 7-111
set_bin_activation() E
example 7-111
environment variables
coverage_backup_database_file() 7-88
VERA_OVERWRITE 10-19
coverage_group 7-3 VERA_SIMULATOR 3-24
embedded VERA_WIDEN_ARGS 3-23
explicit instantiation 7-8
exit_status 2-6
implicit instantiation 7-11
expression
predefined functions 7-100, 7-101, 7-102,
distribution
7-103, 7-104, 7-105, 7-106
syntax 5-33
syntax 7-99
set
predefined tasks 7-102
syntax 5-32
coverage_group_attributes
external declarations 3-41
at_least 7-77
cross_auto_bin_max 7-59
example 7-60 F
syntax 7-60
cross_num_print_missing 7-55 -F 3-9
example 7-56 example 3-10
syntax 7-56 -f
syntax 3-9
coverage_instance() 7-92
foreach
coverage_load 7-91
constraints 5-43
coverage_point
syntax 5-44
definition 7-14
functions
coverage_save_database() 7-89 external default arguments 3-42
coverage_set_database_file_name() 7-88 external functions 3-41
crosses
predefined coverage group methods 7-106
G
-g 3-13
D general options
-D 3-8 -help 3-2

IN-5
-pp 3-3 I
-print 3-3
-I 1-8, 3-16
-proj 3-3
-rvm_version 3-3 -i 3-17
-tem 3-3 -i_skew 3-17
-v 3-3 if-else
-vmc 3-4 production definition 5-91
get_at_least() 7-104 usage in VSG 5-91
get_auto_bin_least() 7-100 ignored 7-47
get_auto_bin_max() 7-100, 7-101, 7-102, implication constraint
7-103, 7-104, 7-105, 7-106 syntax 5-35
get_cov_weight() 7-104 in
constraint expression 5-30
get_cov_weightt() 7-100
set operator 5-32
get_coverage() 7-79
including files 1-8
get_coverage_goal() 7-100, 7-104
inistate() 5-7
get_cross_bin_max() 7-100, 7-106
inst_get_at_least() 7-100, 7-104
get_cycle() 7-74
inst_get_auto_bin_max() 7-100, 7-106
-get_plus_arg 10-20
inst_get_collect() 7-100
get_plus_arg() 3-39
inst_get_cov_weight() 7-100, 7-105
get_time() 7-74
inst_get_coverage_goal() 7-100, 7-105
getstate() 5-9
inst_get_cross_bin_max() 7-100, 7-106
GUI debbugger
inst_query() 7-99, 7-100, 7-105
Vera 1-9
inst_set_at_least() 7-102, 7-105
inst_set_auto_bin_max() 7-102, 7-106
H inst_set_bin_activation 7-100
-H 3-13 inst_set_bin_activation()
-h 3-13 syntax 7-110
-HC 3-15 inst_set_collect() 7-102
-HCnu 3-16 inst_set_cov_weight() 7-102, 7-105
HDL_filename.v inst_set_coverage_goal() 7-102, 7-105
definition of 1-9 inst_set_cross_bin_max() 7-103, 7-106
hdl_node 2-18 installation guide
header files 3-13 location of 2-4
-help 3-2 instance-specific
plus arguments 12-14
-Hnu 3-16
interface specifications
-hnu 3-16
generating ASCII text files 3-17
-ip 3-22

IN-6
K N
keywords -no_dep_graph
big_endian 6-5 -y 3-23
bit_normal 6-5 -no_depth_graph 3-18
bit_reverse 6-5 NO_VARS 5-84
little_endian 6-4 -no_warn_null 3-19
packed 6-5 null
prod 5-95 object handles 6-8
prodget 5-97
prodset 5-96
randcase 5-12 O
randseq 5-86 object files
unpacked 6-5 Vera 12-11
OK_LAST 5-84
L OpernVera assertion classes 9-2
OpernVera assertion operations 9-2
line wrapping 3-3
little_endian 6-4
load() 7-103 P
-local 3-18 pack() 6-6, 6-8
example 6-10
post_pack() 6-10
M pre_pack() 6-10
m_state 7-29 syntax 6-7
m_trans 7-37 packed 6-4
mailboxes packed bit_normal, 6-5
setting maximum number 3-35
packing and unpacking
main-specific pack() 6-6
plus arguments 12-13 property attributes 6-4
manual seeding unpack() 6-8
srandom() 5-10
packing methods 6-6
-max_error 3-18 attributes for
-max_error_number 3-18 big_endian 6-5
-mhdl 2-21 bit_normal 6-5
mixed HDL 2-17 bit_reverse 6-5
SRO_MX 2-22 little_endian 6-4
VCS_MX 2-17 plus arguments
MTI VHDL, compiling with 9-25 plus argument requests
CHECK 3-39
HNUM 3-39

IN-7
NUM 3-39 FIRST 7-114
STR 3-39 GOAL 7-114
post_boundary() 5-84 NEXT 7-114
syntax 5-85 NUM_BIN 7-114
post_pack() 6-10 SAMPLE 7-114
post_randomize() 5-23 SUM 7-114
post_unpack() 6-10 query_str() 7-101, 7-105
-pp 3-3 quiet mode 3-21
-Pprinter 3-3
pre_boundary() 5-84 R
syntax 5-84
rand 5-24
pre_pack() 6-10
rand_mode() 5-22, 5-70
pre_randomize() 5-23
syntax 5-70
pre_unpack() 6-10
rand48() 5-16
preprocessor options
randc 5-24
-I 3-16
randcase 5-12–5-13
-print 3-3
random number generators
-print_deps 3-19
getstate() 5-9
-y 3-23
inistate() 5-7
printing Vera files 3-3 rand48() 5-16
prodget() 5-97, 5-98 random() 5-14
prodset() 5-96 setstate() 5-8
production definitions 5-87 srandom() 5-7
production items 5-87 urand48() 5-16
weights 5-87 urandom() 5-15
production weights 5-90 urandom_range() 5-17
profiler, memory 10-7 random numbers
-proj 3-3 +vera_random_v0 3-31
project files setting seeds at compile time 3-38
#define 12-2 random() 5-14, 5-93
#include 12-2 -random_compat 3-22
main 12-2 random_compat
property attributes vera_restore_rng_state() 5-12
vera_save_rng_state() 5-12
randomize() 5-18
Q syntax 5-65
-q 3-21 randomize() with 5-20
query() 7-74, 7-101, 7-105, 7-113 syntax 5-66
query() commands randseq 5-86, 5-89, 5-94, 5-99
COVERAGE 7-114 syntax to define block 5-86

IN-8
regions syntax 7-109
setting maximum number 3-38 set_cov_weight() 7-102, 7-105
repeat set_coverage_goal() 7-102, 7-105
usage in VSG 5-93 set_cross_bin_max() 7-102, 7-106
repeat loops 5-93 set_name() 7-103
random() 5-93
setstate() 5-8
-rvm_version 3-3
-shell 3-25
shell file
S Vera 1-6
solve 5-41
sample
syntax 7-14 srandom() 5-7
samples state
predefined coverage group methods 7-106 not 7-31
samples or crosses wildcard 7-33
predefined coverage group methods 7-104 stream generation
sampling events, types of production definitions 5-86
clock edge stream generator
syntax 7-62 randseq 5-86
general task calls subroutines
example 7-65 declaring external 3-41
ova events external default arguments 3-42
example 7-64 external definitions
signal edge declaring external subroutines 3-41
syntax 7-62 external subroutines 3-41
signal edges surround-by-X 12-8
clock edge SystemC
example 7-62 calling OpenVera tasks from 2-30
sync events calling tasks from OpenVera 2-30
example 7-63 creating an interface 2-26
syntax 7-63 flow 2-25
variable changes running with OpenVera 2-27
example 7-62
-systemc 3-22
syntax 7-62
SystemClock 1-7, 12-9
save/restart 10-17, 10-18
semaphores
setting maximum number 3-38 T
set expression 5-32
-t 1-8
set_at_least() 7-102, 7-105 tasks
set_auto_bin_max() 7-102, 7-106 external default arguments 3-42
set_bin_activation 7-101 external tasks 3-41
set_bin_activation()

IN-9
-tdef 3-22 urandom_range() 5-17
-tem 3-3
template generator 1-7
invoking 3-3
V
-tem 1-7 -V 3-4
template file, blank 2-8, 2-15 -v 3-3
template options value passing
-c 1-8 value declaration 5-95
-I 1-8 prod 5-95
-t 1-8 value passing functions
test_top files prodget() 5-96
generating test_top files 3-26 prodset() 5-96
testbench properties randseq blocks 5-96
Vera properties variables
vera_profile_start 3-31 forward referencing 3-41
text macros 3-8, 3-35 referencing 3-41
timescale .vcon
statement 12-3 SystemClock 12-5
switch 3-25 .vcon file, direct connection using 12-3
-top 3-26 Vera project file 12-2
-tradition 3-22 Vera runtime options
trans 7-35, 7-42 +enable_solver_trace 3-34
all 7-38 +enable_solver_trace_on_failure 3-34
not 7-38 +vera_continue_on_error 3-28
wildcard 7-40 +vera_debug_on_error 3-28
+vera_debug_on_start 3-29
+vera_directc 3-34
U +vera_stop_on_end 3-32
unpack() 6-8, 6-10 +vera_stop_on_error 3-32
example 6-10 +vera_text_debug 3-32
syntax 6-8 +vera_udf 3-38
unpacked 6-4, 6-5 coverage_control 3-34
unpacking methods 6-8 vera_aspects 3-33
attributes for vera_cache_dir 3-33, 5-77
big_endian 6-5 vera_debug_on_error 3-28
bit_normal 6-5 vera_debug_on_int 3-28
bit_reverse 6-5 vera_directc 3-34
little_endian 6-4 vera_disable_final_report 3-29
unpack() 6-8 vera_disable_random_stability 3-29
urand48() 5-16 vera_dyn 3-29
vera_enable_mprint 3-29
urandom() 5-15

IN-10
vera_exit_on_error 3-29 syntax 5-75
vera_full_conflict_info 3-29 vera_enable_solver_trace_on_failure
vera_inst_path 3-34 syntax 5-76
vera_interactive_plot 3-29, 3-30 vera_plot() 11-2
vera_load 3-34 syntax 11-2
vera_mailbox_size 3-35 vera_profile_sort_by_name 10-4
vera_main_name 3-30 vera_profile_start 10-4
vera_mload 3-35
vera_random_see_automatic 3-31
vera_mload_define 3-35
vera_report_profile() 10-2, 10-8
vera_no_hdl_task_semaphore 3-30
vera_object_filename 3-35 vera_restore_rng_state()
example 5-11
vera_path_sep 3-30
random_compat 5-12
vera_pload 3-36
syntax 5-11
vera_pload_define 3-36
vera_plot 3-36, 11-2 vera_save_rng_state()
vera_profile_filename 3-36, 10-4, 10-9 example 5-11
vera_profile_interval 3-36 random_compat 5-12
vera_profile_limit 3-37, 10-4 syntax 5-11
vera_profile_object 3-30 VERA_WIDEN_ARGS 3-23
vera_profile_object_verbose 3-30, 10-14 VeraDyn.vrh 10-23
vera_profile_range 3-37 vera.ini
vera_profile_sort_by_name 3-31, 10-4 example of 10-3
vera_rand48_seed 3-38 verilog_task 2-19
vera_random_see_automatic 3-31 importing 2-19
vera_random_seed 3-38 veritask 12-9
vera_random_v0 3-31 vhdl_task 2-19
vera_region_size 3-38 importing 2-19
vera_semaphore_size 3-38 vLoad() 10-25
vera_solver_mode 3-38, 5-77 -vlog 3-23, 3-24, 3-26
vera_text_debug 3-32
-vmc 3-4
vera_use_system_random 3-32
VRO
vera_vros 3-38
dynamic loader 10-22
Vera shell file 1-6
VSG
Vera standalone 1-10 if-else usage 5-91
VERA Stream Generator overview 5-86
See VSG. prodget() 5-97
vera_coverage_control 3-34 prodset() 5-96
vera_cs 1-10 production definitions 5-87
-vera_dbind 2-21 production weights 5-90
vera_disable_final_report 3-29 randseq 5-86
vera_enable_solver_trace usage of case 5-92

IN-11
usage of continue 5-94 weights 5-90
usage of repeat 5-93 -widen_args 3-23
use of break 5-94
vUnLoad() 10-26
vUnloadAll() 10-26 Y
-y 3-23
-dep_check 3-23
W -print_deps 3-23
-w 3-3

IN-12

Вам также может понравиться