Vous êtes sur la page 1sur 38

VMM for SystemVerilog

Companion Guide

Version 1.1, December 2007

Copyright © 2006-2007 Doulos Ltd. All Rights Reserved

The information contained herein is the property of


Doulos Ltd. and is supplied without liability for errors or
omissions. No part may be used, stored, transmitted
or reproduced in any form or medium without the
written permission of Doulos Ltd.

Doulos® is a registered trademark of Doulos Ltd.

Trademarks/Copyright ©2006 Synopsys, Inc. All


Rights Reserved.

VCS is a registered trademark of Synopsys, Inc.

Copyright © 2006 ARM Ltd. All rights reserved.

ARM is a registered trademark of ARM Ltd.

First published in 2006 by Doulos

Doulos
Church Hatch
22 Market Place
Ringwood
Hampshire
BH24 1AW
UK

Tel +44 (0) 1425 471223


Fax +44 (0) 1425 471573

Email: info@doulos.com
Web: http://www.doulos.com
VMM for SystemVerilog
Companion Guide

This Companion Guide provides a handy quick reference for users of the
Verification Methodology Manual (VMM) for SystemVerilog, a professional
book co-authored by verification experts from ARM Ltd. and Synopsys, Inc.
and published by Springer Science and Business Media (ISBN 0-387-25538-
9).

The Companion Guide is not intended to replace either the VMM for
SystemVerilog or a proper training course. It assists the engineer in
identifying the exact signature of a particular method, or the set of methods
they have inherited from a certain base class. It is suitable as a very brief
technical introduction to the aims and structure of the VMM methodology, and
also contains reference information on how to use the VMM Standard Library
®
with the Synopsys VCS solution.

Complete code for the Example VMM System, as outlined on pages 7 to 14,
can be downloaded from the Doulos web site:

http://www.doulos.com/knowhow/sysverilog

1
2
Introduction
The VMM for SystemVerilog describes a flexible, scalable verification
methodology for SystemVerilog users. It is possible to use concepts from the
VMM methodology both in small ad-hoc testbenches for module testing and
in the creation of large, complex high-grade verification environments by
specialized verification engineers.
The VMM for SystemVerilog contains detailed implementation rules and
recommendations to aid in the adoption of this methodology. These rules and
recommendations can also provide useful guidance for those who are new to
complex verification.
The VMM Standard Library provides base classes for key aspects of the
verification environment, an event notification service, and a message
logging service. VMM-compliant test environments must use these base
classes, suitably extended to provide any required custom functionality.
Transaction data in a VMM-compliant testbench are objects of one or more
user-defined classes derived from the provided base class vmm_data. Such
objects are produced by a transactor, which is derived from vmm_xactor.
Some transactors are the source of a data stream, generating data according
to constraints; they are known as generators. Other transactors take data
items from a channel, perform some transformation, then add the item to a
downstream channel; they are said to be functional-level transactors. Some
transactors at the lowest level of the testbench, communicating directly with
the design by means of a pin-level interface, are known as command-level
transactors.
Transactors pass transactions from one to another through channels. A
generator creates a series of data items, then places references to those
date items into a channel. Another transactor can read the next reference
from the channel and perform any required operation on that data before
placing the reference in the next channel. The creation of channels for any
given transaction type is automated by a macro `vmm_channel.
A notification service, based on vmm_notify, gives us much more than is
available using event variables. The operation of the notification is defined at
configuration time, and notification can have status and timestamp
information attached. Notification is used by transactors and channels to
mark activity and for synchronization.
The environment, based on vmm_env, is where all these objects are
instanced. At the top of the object instance hierarchy is the testcase, which
chooses, configures and runs a particular environment. The testcase is
remote from the event-driven world of signals, but has the ability to control
the environment at any level.

3
Introduction
A single source of transactions can feed many consumers using a
vmm_broadcast object. Conversely, multiple sources can be merged into a
single stream of transactions using vmm_scheduler.
The message service, based on vmm_log, provides a mechanism for
reporting interesting activity to output files or the simulator console. Using a
predefined message mechanism gives us consistency (post-processing and
interpretation), localization (identification and control of source),
configurability (control of message severity and type), and control (effect on
simulation behavior). All textual output from a VMM-compliant test
environment should use the message service.

4
Introduction
The diagram below shows the structure of a small VMM-compliant testbench.
The transactors that drive the DUT form a protocol stack, with the simplest
transactions (signal transitions) at the lowest level of DUT interface, and the
most complex (scenarios) coming from the generator at the top. We show
one level of functional-level transactor, but there could be more if required.
Similarly, the monitoring transactors form a protocol stack. Connection to the
DUT is implemented in a standardized way using the SystemVerilog
interface construct – see the extended example, and the section on
Command-level transactors, for more detail.

Program Test case

test_env env = new;


env.run; Constraints

Environment - vmm_env

Generator Scenario-level
Scenario-level
vmm_atomic_gen Callback scoreboard Callback

vmm_channel

Transactor Functional-level Monitor


Functional-level vmm_xactor scoreboard vmm_xactor
Callback Callback

vmm_channel vmm_channel

Transactor Monitor
Command-level
vmm_xactor vmm_xactor

Virtual interface Virtual interface

Test harness
Interface Interface

DUT

Note:
Callbacks from a generator use a façade class derived from
atomic_gen_callbacks. Callbacks from other transactors use a façade
derived from vmm_xactor_callbacks.

5
6
Example VMM System
Defining transaction data
We start by describing our transaction data using an extension of vmm_data.
We describe how a transaction is made up, with constraints that define
suitable data values; and we supply necessary methods, including a deep
copy and a method for checking data validity.

class packet_trans extends vmm_data;


import types::*;
static vmm_log log = new ("packet_trans", "class");

// User-defined data contents of the transaction, declared rand


rand packet_t packet;

// Each transaction is given a unique serial number


static byte packet_num;
byte this_packet_num;

// Example constraint, creates a packet with useful values


constraint reasonable {
packet.header == 8'h33;
packet.src == 1;
packet.length==packet.payload.size;
}

function new();
super.new(this.log);
this_packet_num = packet_num;
packet_num++;
endfunction
// Other constraints, functions such as copy() required by VMM, etc.

endclass: packet_trans

// Automatically create a channel class packet_trans_channel


`vmm_channel(packet_trans)

7
Example VMM System

Creating a generator and a command-level transactor


Now we have described our transaction data and a channel class to carry it,
we can make some instances of transactions. We declare a class to generate
packet_trans objects by using the atomic-generator macro:

`vmm_atomic_gen(packet_trans)

This declares a class called packet_trans_atomic_gen, which we can


instance in the environment (see Creating the environment, later in this
section):

packet_trans_atomic_gen gen;

When we construct an object of this type we connect it to a channel, into


which it passes references to the data items it generates.
Transactors that sit at the lowest level of the testbench hierarchy are also
derived from vmm_xactor, and connected directly to the design by means of
a virtual interface:

class packet_master extends vmm_xactor;

virtual ex_intf.test V;
packet_trans_channel in_chan;

function new (string name,


int stream_id = -1,
virtual ex_intf.test V,
packet_trans_channel in_chan = null);
super.new("packet_master", name);
this.V = V;
if (in_chan == null)
in_chan = new("packet_trans_channel",
"packet_master_DEFAULT_IN_CHAN");
this.in_chan = in_chan;
endfunction

8
Example VMM System
task main;
packet_trans p;
fork
super.main();
join_none;
forever begin
this.wait_if_stopped_or_empty(this.in_chan);
this.in_chan.get(p);
sendapacket(p);
end
endtask

task sendapacket(input packet_trans_data p);


logic [7:0] buffer[];
p.byte_pack(buffer);
foreach (buffer[i]) @(V.cb) begin
V.cb.data_in <= buffer[i];
if (buffer[i] == p.packet.header)
V.cb.sync <= 1'b1;
else
V.cb.sync <= 1'b0;
end
endtask

// other functions and tasks for stimulus and observation


endclass

9
Example VMM System

Creating a channel
We have already created a channel class to transfer our packet_trans data
using the vmm_channel macro. Now we can make an instance of it:

packet_trans_channel in_chan;

Then within the transactors we use the channel's methods, as in the


transactor above. An atomic generator does this automatically.

Creating the environment


We bring together all our system building blocks as objects instanced in a
derivative of vmm_env.

class dut_env extends vmm_env;


virtual ex_intf.test intf;
packet_trans_channel gen2mst;
packet_trans_channel mon2scb;
packet_trans_atomic_gen gen;
packet_master mst;
packet_monitor mon;
dut_sb scb;
...
endclass: dut_env

This class declaration has several key features:


1) a virtual interface, for connecting to the design.
2) A connection to the messaging service vmm_log.
3) Two channel instances.
4) An atomic generator.
5) A master transactor.
6) A monitor, or passive transactor.
7) A scoreboard (implementation not described here).

The generator produces a stream of data instances, and will put each one
into the channel gen2mas. The master transactor uses the get() method
of the channel to retrieve data and stimulate the design.

10
Example VMM System
The monitor watches signal activity for transactions and logs them on the
scoreboard to which it is connected by another channel instance mon2scb.

In the constructor of the environment, we describe the connection to be made


between the design and testbench:

function dut_env::new();
super.new("DUT_ENV");
endfunction

We complete the build() method of the environment to create instances of


all our building blocks. We must also specify the connection to be made
between the design and testbench, using the instance name of an
appropriate interface and modport in the test harness module:

function void dut_env::build();


virtual ex_intf.test ifc;
super.build();
ifc = ex_top.intf.test; // Identify the connection
gen2mst = new ("Packet Trans Channel", "gen2mst");
mon2scb = new ("Packet Trans Channel", "mon2scb");
gen = new ("Atomic Gen", 1, gen2mas);
mst = new ("Transaction master", 1, ifc, gen2mst );
mon = new ("Transaction monitor", 1, ifc, mon2scb);
scb = new (cfg.trans_cnt, mon2scb);

begin // callbacks for scoreboard


packet_mst_sb_callbacks packet_mst_sb_cb = new(scb);
mst.append_callback(packet_mst_sb_cb);
end

begin // callbacks for coverage collection


packet_master_cov_callbacks cov_cb = new();
mst.append_callback(cov_cb);
end

gen.stop_after_n_insts = 20;
endfunction: build

11
Example VMM System
Within the build method we are registering callbacks with each transactor. In
short, each time a transactor does anything it should call a function to provide
a hook for optional related actions. In this case it is to add the transaction to
the scoreboard and to establish coverage of transactions, but callbacks can
also modify or drop data, or insert some directed test data using the
inject() method that should be found in every transactor.

We fill in the start() method with actions necessary to get our testbench
going:

task dut_env::start();
super.start();
gen.start_xactor();
mst.start_xactor();
mon.start_xactor();
scb.init();
endtask: start

12
Example VMM System

Test program:

This is a SystemVerilog program that constructs an instance of the


environment and calls the methods defined in the environment class. The
program takes as input an interface instance to which the test environment
will be connected.

program testprogram;

dut_env env; // DUT Environment instance

initial begin

// Create the environment, connect it to the DUT via modport test


// of interface instance intf inside the test harness ex_top
env = new(ex_top.intf.test);

// Run everything. The environment will detect that its


// build method has not yet been called, and will call it automatically
env.run();

end

endprogram: testprogram

13
Example VMM System

Test harness:

The test harness is a SystemVerilog module containing the DUT, its


supporting connections and clock generators, and the interface instances
needed to link it to the VMM-compliant testbench program. This page shows
only fragments of the code.

• First we create the necessary interface definition:


interface ex_intf (input bit clk);

// Wires for each DUT connection


wire [7:0] data_in; ...

// Clocking block specifies direction and synchronization


clocking cb @(posedge clk);
output sync, data_in;
endclocking: cb

// Modport makes clocking block available to testbench


modport test(clocking cb);
endinterface: ex_intf

• Now we create a module instancing the DUT and interface.


module ex_top;

// Interface instance, provides bridge to testbench


ex_intf intf;

// DUT instance, directly wired to signals in the interface


top_design DUT (.clock(clk), .sync(intf.sync) ...);
endmodule: ex_top

14
Quick Reference Listings
Several kinds of base class are defined in the VMM Standard Library.
vmm_data is a template for data objects/transactions that are manipulated
by the system. Transaction data objects are likely to be created and
destroyed dynamically, in large numbers, during normal operation of the
testbench.
vmm_env, vmm_xactor and vmm_channel (including vmm_broadcast
and vmm_scheduler) are a base for components of the testbench. They
create, convey and transform objects based on vmm_data. Objects of these
types are likely to be created once only, as part of the environment’s build
procedure, and together form the verification environment.
Macros `vmm_atomic_gen and `vmm_scenario_gen simplify the creation
of generators – derivatives of vmm_xactor designed to generate streams of
transactions based on random constraints.
vmm_notify and vmm_log respectively allow control and reporting of what is
going on.

15
vmm_data Base class
This is the base class from which all user-defined transaction data types
should be derived. It provides a set of methods that all data or transaction
descriptors need, such as for copying, comparing and checking. Virtual
methods in bold must be overridden in all derived classes.

class vmm_data;

function new(vmm_log log);


function vmm_log set_log(vmm_log log);
int stream_id;
int scenario_id;
int data_id;
vmm_notify notify;
enum { EXECUTE, STARTED, ENDED };
function void display(string prefix = "");
virtual function string psdisplay ( string prefix = "" );
virtual function bit is_valid ( bit silent = 1, int kind = -1 );
virtual function vmm_data allocate ( );
virtual function vmm_data copy ( vmm_data to = null );
virtual function bit compare (
input vmm_data to, output string diff, input int kind = -1 );
virtual protected function void copy_data ( vmm_data to );
virtual function int unsigned byte_pack (
ref logic [7:0] bytes [ ], int unsigned offset = 0, int kind = -1 );
virtual function int unsigned byte_unpack (
const ref logic [7:0] bytes [ ], input int unsigned offset = 0,
input int len = -1, input int kind = -1 );
virtual function int unsigned byte_size ( int kind = -1 );
virtual function int unsigned max_byte_size ( int kind = -1 );
virtual function void save ( int file );
virtual function bit load ( int file );

16
Creating an extension of vmm_data

• First, decide what data you need in your transaction. There are no
restrictions on user-defined data that can be added to an extension of
vmm_data, but all data fields that represent part of a transaction must
be declared rand so that their values can be randomized if required.
The section Class Properties/Data Members in chapter 4 of the VMM
book gives more detail of appropriate ways to model transaction data.
• Create constraints that control the randomization of your data fields.
You are free to design these constraints to determine the content,
distribution and validity of your randomly generated data. You should
name the constraints in a consistent way so it is easier to document and
extend them. The VMM stipulates a few simple rules concerning these
user-defined constraints; you can find these rules in chapter 4 of the
book.
• Write virtual method definitions for the base class methods that must be
overridden: copy, compare, allocate, is_valid, psdisplay.
Details of the standard design patterns for these methods can be found
in the VMM book, and the utility rvmgen (described at the end of this
guide) can construct a code skeleton to save you some work.
• Although it is not mandatory, any non-trivial derivative of vmm_data is
sure to need its own implementation of the constructor new.

• Immediately after defining the new derived class, invoke the


`vmm_channel macro to construct a channel for the new class.
• Optionally, invoke one or both of the generator macros
`vmm_atomic_gen or `vmm_scenario_gen to construct new class(es)
that can automatically generate randomized streams of objects of the
vmm_data extension you have defined.
• Create appropriate derived classes from vmm_xactor (see below) to
manipulate the new data type. If the transaction represents a data
stream that appears directly at the ports of the DUT, or elsewhere in the
test harness, then it will be necessary to create a command-level
transactor.

17
vmm_xactor Base class
All transactors are derived from this base class, including bus-functional
models, monitors and generators. It provides a standard set of methods that
all transactors need.

class vmm_xactor;

function new ( string name, string instance, int stream_id = -1 );


virtual function string get_name ( );
virtual function string get_instance ( );
vmm_log log;
int stream_id;
virtual function void prepend_callback ( vmm_xactor_callbacks cb );
virtual function void append_callback ( vmm_xactor_callbacks cb );
virtual function void unregister_callback ( vmm_xactor_callbacks cb );
vmm_notify notify;
// Enumeration values for the state of the transactor:
enum { XACTOR_IDLE, XACTOR_BUSY,
XACTOR_STARTED, XACTOR_STOPPED, XACTOR_RESET };
virtual function void start_xactor ( );
virtual function void stop_xactor ( );
virtual function void reset_xactor ( reset_e rst_typ = SOFT_RST );
protected task wait_if_stopped ( );
protected task wait_if_stopped_or_empty ( vmm_channel chan );
protected virtual task main ( );
virtual function void save_rng_state ( );
virtual function void restore_rng_state ( );
virtual function void xactor_status ( string prefix = "" );
// Macro to simplify the calling of callback methods:
`vmm_callback ( callback_class_name, method ( args ) )

18
Command-level transactors
At the lowest level of the testbench structure, a command level transactor
provides the bridge between the object-oriented, class-based world of the
testbench and the module-based world of the DUT together with its
supporting test harness including clock generators, module-to-module
interconnections and so on. There is a standard implementation pattern for
this bridge, exploiting SystemVerilog’s interface, clocking and
virtual interface constructs. In summary:

Implementation of the test harness


• The test harness is a module that instances the DUT together with any
wiring and supporting models that it requires.
• Clocks must be generated in module-based code in the test harness.
• All signals that will be handled by the testbench must be implemented
as Verilog nets (wire) encapsulated in an interface that is instanced
in the test harness.
• This interface must contain a clocking block for each different
clock signal that it uses. The clocking block must capture all the nets
that will be used in the testbench, and these nets must be given
appropriate direction (input, output, inout) in the clocking block.
• The clocking block must be passed through a modport of the interface.
No other signals should pass through this modport.
• Nets in the interface may be connected to corresponding nets in the
DUT or test harness by continuous assignment (for unidirectional
signals) or by alias statements (for inout signals). Alternatively, the
DUT's ports may be connected directly to signals in the interface using
the DUT's port connection list.

Implementation of the command-level transactor


• The command-level transactor is an extension of vmm_xactor. It must
have a public class property that is a virtual interface whose data
type matches the modport described above.
• At some point in construction of the environment – typically as part of
the constructor of the command-level transactor – this
virtual interface property must be set to reference the instance of
the modport that is required.
• The transactor now has access to the clocking block via this
virtual interface property.

19
vmm_channel Macro and base class
Base class vmm_channel implements a generic transaction-level interface
mechanism. Properties and virtual methods of vmm_channel are
summarized on the facing page.

Users should invoke the `vmm_channel macro to define a channel class


specialized for a particular derivative of vmm_data. This macro automates
the extension of the channel base class vmm_channel.

Macro `vmm_channel defines a class named class_name_channel,


derived from base class vmm_channel, for any user-specified class_name.

`vmm_channel ( class_name )

This macro creates a new channel class definition. It does not instance
anything.

It is not usually necessary to modify or extend the resulting specialized


channel class class_name_channel.

class class_name_channel extends vmm_channel;

function new ( string name, string instance,


int unsigned full = 1, int unsigned empty = 0, bit fill_as_bytes = 0 );
vmm_log log;
vmm_notify notify;
function void reconfigure (
int full = -1, int empty = -1, logic fill_as_bytes = 1'bx );
function int unsigned full_level ( );
function int unsigned empty_level ( );
function int unsigned level ( );
function int unsigned size ( );
function bit is_full ( );
function void flush ( );
function void sink ( );
function void flow ( );

20
Macro and base class vmm_channel

continued

function void lock ( bit [1:0] who );


function void unlock ( bit [1:0] who );
function bit is_locked ( bit [1:0] who );
task put ( class_name obj, int offset = -1 );
function void sneak ( class_name obj, int offset = -1 );
function class_name unput ( int offset = -1 );
task get ( output class_name obj, input int offset = 0 );
task peek ( output class_name obj, input int offset = 0 );
task activate ( output class_name obj, input int offset = 0 );
function class_name active_slot ( );
function class_name start ( );
function class_name complete ( vmm_data status = null );
function class_name remove ( );
function active_status_e status ( );
task tee ( output class_name obj );
function bit tee_mode ( bit is_on );
function void connect ( vmm_channel downstream );
function class_name for_each ( bit reset = 0 );
function int unsigned for_each_offset ( );
function bit record ( string filename );
task bit playback ( output bit success, input string filename,
input vmm_data loader, input bit metered = 0 );

21
vmm_notify Base class
The vmm_notify class implements an interface to the notification service,
used for synchronization between concurrent threads or transactors. It
provides more functionality than is available using event variables.

class vmm_notify;

function new ( vmm_log log );


virtual function vmm_notify copy ( vmm_notify to = null );
virtual function int configure ( int notification_id = -1,
sync_e sync = ONE_SHOT );
virtual function int is_configured ( int notification_id );
virtual function bit is_on ( int notification_id );
virtual task wait_for ( int notification_id );
virtual task wait_for_off ( int notification_id );
virtual function bit is_waited_for ( int notification_id );
virtual function void terminated ( int notification_id );
virtual function vmm_data status ( int notification_id );
virtual function time timestamp ( int notification_id );
virtual function void indicate (
int notification_id, vmm_data status = null );
virtual function void set_notification (
int notification_id, vmm_notification ntfy = null );
virtual function vmm_notification get_notification ( int notification_id );
virtual function void reset (
int notification_id = -1, reset_e rst_typ = SOFT );

Class vmm_notification is used to describe a notification that can be


autonomously set (indicated) or reset based on a user-defined occurrence,
such as a combination of other notifications or external events.

class vmm_notification;

virtual task indicate ( ref vmm_data status );


virtual task reset ( );

22
Macro vmm_atomic_gen
This macro is used to define a class named class_name_atomic_gen for
any user-specified class class_name that is derived from vmm_data. The
resulting generator class is an extension of vmm_xactor.

`vmm_atomic_gen ( class_name, class_description_string )


Creates class class_name_atomic_gen (see below)

class class_name_atomic_gen extends vmm_xactor;

function new ( string instance, int stream_id = -1,


class_name_channel out_chan = null );
class_name_channel out_chan;
int unsigned stop_after_n_insts;
class_name randomized_obj;
enum { GENERATED };
enum { DONE };
virtual task inject ( class_name data, ref bit dropped );

23
vmm_scenario_gen Macro
Macro `vmm_scenario_gen ( class_name, class_description_string )
defines the following classes:

class class_name_scenario_gen extends vmm_xactor;


Transactor class to implement a scenario generator.
function new ( string instance, int stream_id = -1,
class_name_channel out_chan = null );
class_name_channel out_chan;
int unsigned stop_after_n_insts;
int unsigned stop_after_n_scenarios;
class_name_scenario scenario_set [ $ ];
class_name_scenario_election select_scenario;
enum { GENERATED };
enum { DONE };
virtual task inject_obj ( class_name obj );
virtual task inject ( class_name_scenario scenario );

class class_name_atomic_scenario;
Implements a scenario composed of a single unconstrained transaction.
int unsigned ATOMIC;
constraint atomic_scenario;

class class_name_scenario;

static vmm_log log;


int stream_id;
int scenario_id;
function int unsigned define_scenario (
string name, int unsigned max_len );
function void redefine_scenario (
int unsigned scenario_kind, string name, int unsigned max_len );
function string scenario_name ( int unsigned scenario_kind );

24
Macro vmm_scenario_gen

class class_name_scenario; continued

rand int unsigned scenario_kind;


rand int unsigned length;
rand class_name items [ ];
class_name using;
rand int unsigned repeated;
static int unsigned repeat_thresh;
function void allocate_scenario ( class_name using = null );
function void fill_scenario ( class_name using = null );
virtual task apply (
class_name_channel channel, ref int unsigned n_insts );

class class_name_scenario_election;
Implements a random selection process for selecting the next scenario
descriptor to be randomized, from a set of available descriptors stored in
its scenario_set queue variable.
int stream_id;
int scenario_id;
int unsigned n_scenarios;
int unsigned last_selected [ $ ];
int unsigned next_in_set;
class_name_scenario scenario_set [ $ ];
rand int select;
constraint round_robin;

class class_name_scenario_gen_callbacks;
Defines a façade for the scenario generator’s callbacks.
virtual task pre_scenario_randomize ( class_name_scenario_gen gen,
ref class_name_scenario scenario );
virtual task post_scenario_gen ( class_name_scenario_gen gen,
class_name_scenario scenario, ref bit dropped );

25
vmm_broadcast Base class

If multiple consumers attempt to get transactions from a standard VMM


channel, the transaction descriptors are distributed among the consumers so
that each of the N consumers sees 1/N descriptors. If multiple consumers
must each see all the descriptors, vmm_broadcast can be used to feed
descriptors from one source to an arbitrary number of consumers. Each
output channel of a vmm_broadcast component can be configured to
provide either a reference to the transaction or a copy of that transaction. If a
particular channel needs to change the data without affecting other
consumers then it must copy the data. References or copies can be set as
the default for a vmm_broadcast component.

class vmm_broadcast;

vmm_log log;
typedef enum { AFAP, ALAP } bcast_mode_e;
function new ( string name, string instance, vmm_channel source,
bit use_references = 1, bcast_mode_e mode = AFAP );
virtual function void start_xactor ( );
virtual function void stop_xactor ( );
virtual function void reset_xactor ( reset_e rst_type = SOFT_RST );
broadcast_mode ( bcast_mode_e mode );
virtual function int new_output (
vmm_channel channel, logic use_references = 1'bx );
virtual function void bcast_on ( int unsigned output_id );
virtual function void bcast_off ( int unsigned output_id );
virtual protected function bit add_to_output ( int unsigned decision_id,
int unsigned output_id, vmm_channel channel, vmm_data obj );

26
Base class vmm_scheduler
This class is the reverse of the vmm_broadcast class. It handles multiple
sources feeding data into a channel with only one consumer. If a multipoint-
to-point mechanism must follow a specific scheduling algorithm, a
vmm_scheduler component can be used to control the choice of source
stream providing the next transaction to the output stream.

class vmm_scheduler;

vmm_log log;
protected vmm_channel out_chan;
function new ( string name, string instance,
vmm_channel destination, int instance_id = -1 );
virtual function void start_xactor ( );
virtual function void stop_xactor ( );
virtual function void reset_xactor ( reset_e rst_typ = SOFT_RST );
virtual function int new_source ( vmm_channel chan );
virtual function void sched_on ( int unsigned input_id );
virtual function void sched_off ( int unsigned input_id );
virtual protected task schedule ( output vmm_data obj,
input vmm_channel sources [ $ ], int unsigned input_ids [ $ ] );
virtual protected task get_object ( output vmm_data obj,
vmm_channel source, int unsigned input_id, int offset );
vmm_scheduler_election randomized_sched;

27
vmm_log Base classes
This class is used to connect to the message service, for reporting events
and interesting occurrences. Note: owing to the size of this class, this is not
an exhaustive list. More details can be found in the full description of
vmm_log in appendix A of the VMM book.

vmm_log_format is a class that describes the formatting of messages. It is


used in the set_format method of vmm_log:

class vmm_log_format;

virtual function string format_msg ( string name,


string instance, string msg_typ, string severity, string lines [ $ ] );
virtual function string continue_msg ( string name,
string instance, string msg_typ, string severity, string lines [ $ ] );
virtual function string abort_on_error ( int count, int limit );
virtual function string pass_or_fail ( bit pass, string name, string instance,
int fatals, int errors, int warnings, int dem_errs, int dem_warns );

The following macros are a convenient shorthand for using a vmm_log


instance to produce a message that can be expressed as one string:

`vmm_fatal ( vmm_log log, string txt )


`vmm_error ( vmm_log log, string txt )
`vmm_warning ( vmm_log log, string txt )
`vmm_note ( vmm_log log, string txt )
`vmm_trace ( vmm_log log, string txt )
`vmm_debug ( vmm_log log, string txt )
`vmm_verbose ( vmm_log log, string txt )
`vmm_report ( vmm_log log, string txt )
`vmm_command ( vmm_log log, string txt )
`vmm_transaction ( vmm_log log, string txt )
`vmm_protocol ( vmm_log log, string txt )
`vmm_cycle ( vmm_log log, string txt )

28
Base classes vmm_log

class vmm_log;

function new ( string name, string instance, vmm_log under = null );


virtual function void is_above ( vmm_log log );
virtual function vmm_log copy ( vmm_log to = null );
virtual function string get_name ( );
virtual function string get_instance ( );
virtual function void list ( string name = "/./",
string instance = "/./", bit recurse = 0 );
enum { FAILURE_TYP, NOTE_TYP, DEBUG_TYP,
TIMING_TYP, XHANDLING_TYP, REPORT_TYP,
PROTOCOL_TYP, TRANSACTION_TYP, COMMAND_TYP,
CYCLE_TYP, INTERNAL_TYP, DEFAULT_TYP, ALL_TYPS };
enum { FATAL_SEV, ERROR_SEV, WARNING_SEV,
NORMAL_SEV, TRACE_SEV, DEBUG_SEV,
VERBOSE_SEV, DEFAULT_SEV, ALL_SEVS };
enum { IGNORE, CONTINUE, DUMP_STACK,
STOP_PROMPT, DEBUGGER, COUNT_ERROR,
ABORT_SIM, DEFAULT_HANDLING };
virtual function vmm_log_format set_format ( vmm_log_format fmt );
virtual function bit start_msg( int typ, int sev = DEFAULT_SEV );
virtual function void end_msg ( );
virtual function void enable_types (
int typs, string name = "", string inst = "", bit recursive = 0 );
virtual function void disable_types (
int typs, string name = "", string inst = "", bit recursive = 0 );
virtual function void set_verbosity (
int severity, string name = "", string inst = "", bit recursive = 0 );
virtual function int get_verbosity ( );
virtual function void log_start (
int file, string name = "", string instance = "", bit recurse = 0 );
virtual function void log_stop (
int file, string name = "", string instance = "", bit recurse = 0 );
virtual function void stop_after_n_errors ( int n );
virtual function int get_message_count ( int severity = ALL_SEVS,
string name = "", string instance = "", bit recurse = 0 );

29
vmm_env Base class

This class is used to implement the overall verification environment. It is


extended to create the desired test environment and contains instances of
the class objects used within the particular environment.
Typically, a testcase creates an environment and then calls its run method;
this in its turn calls the test sequencing methods as described below. User
extensions of vmm_env should override these virtual methods to implement
the environment’s construction and functionality.

class vmm_env;

vmm_log log;
vmm_notify notify;
function new ( string name = "Verif Env" );
task run ( );
// Test sequencing methods called by run ( ):
virtual function void gen_cfg ( );
virtual function void build ( );
virtual task reset_dut ( );
virtual task cfg_dut ( );
virtual task start ( );
virtual task wait_for_end ( );
virtual task stop ( );
virtual task cleanup ( );
virtual task report ( );
event end_test;

30
Using the VMM Standard Library with VCS

Synopsys provides you with a ready-to-use implementation of the VMM


Standard Library compiled into the tools.
VCS allows you to see objects in your design and transactions in your
testbench, across multiple design, verification and modelling languages.
The following notes show how to use the VMM Standard Library in simple
cases. For comprehensive information, and for tool-specific issues and
questions, see the VCS product documentation.

Creating your code:


Be sure to include the VMM Standard Library definitions by invoking

`include "vmm.sv"

Compiling with VCS

% vcs -sverilog -debug_all -ntb_opts rvm source_files

-sverilog enables SV parser


-debug_all enables debug capabilities
-ntb_opts rvm enables VMM Standard Library

Running the executable:

% simv

runs in batch mode, and

% simv –gui

runs interactively.

31
Utility program rvmgen
The rvmgen utility provides an easy way to generate source code templates
for VMM-compliant verification components, based on answers to a few
simple questions.

Options:

-L liblist Colon-separated list of user-defined template directories

-X Do not include the standard templates

-l sv Generate template in SystemVerilog

-o fname Generate the template in the specified file

Typical usage:

% rvmgen -l sv

The tool will give you a list of possibilities from the libraries it can see:

From Standard Library:


0) Physical interface declaration
1) Transaction descriptor
2) Driver, Physical-level, Half duplex
3) Driver, Physical-level, Full duplex
4) Monitor, Physical-level, Half duplex
5) Passive Monitor, Physical-level, Full duplex
6) Driver, Functional-level, Half duplex
7) Driver, Functional-level, Full duplex
8) Monitor, Functional-level, Half duplex
9) Passive Monitor, Functional-level, Full duplex
Select [0-9]:

Make the appropriate choice and the code skeleton is generated. “Physical
interface declaration” constructs a SystemVerilog interface block needed
to connect your VMM-compliant testbench to the DUT. The transaction
descriptor is derived from vmm_data; drivers and monitors are derived from
vmm_xactor.

32

Vous aimerez peut-être aussi