Sie sind auf Seite 1von 130

5

Sequences: Constructing Test Scenarios

This chapter describes a uniform and efcient way of implementing sequences in Specman. Specically, this chapter introduces a new statement (the sequence statement), a new action (the do action), and a whole methodology for handling sequences. Together with the evc_util package, Cadence ships three example packages called ex_atm, ex_c_bus, and ex_soc. These example packages demonstrate in detail the various sequence features. Note You can only run these example packages on top of Specman version 4.1 or higher. See the PACKAGE_README.txt les of the example packages for a description of how to run them. The sections of this chapter can be divided into the following four main parts: Introduction

Introduction to Sequences on page 5-2 How to Use Sequences in Your Environment on page 5-4

Basic Use

Getting Started with Sequences on page 5-5 Implementing Sequences on page 5-11 Writing Tests Using Sequences on page 5-18 Sequence File Organization on page 5-23

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-1

Sequences: Constructing Test Scenarios


Introduction to Sequences

Advanced Use

Using Virtual Sequences on page 5-23 Advanced Generation-Related Aspects of Sequences on page 5-29 Implementing Complex Scenarios on page 5-34 Miscellaneous Advanced Features on page 5-48 Layering of Protocols on page 5-55 Tracing and Debugging Sequences on page 5-70

Reference

Sequence-Related Methods on page 5-98 Sequence-Related Pseudo-Routines on page 5-108 Sequence Interface on page 5-110 Predened Sequence Kinds on page 5-117 BFM-Driver-Sequence Flow Diagrams on page 5-119 Sequence Deprecation on page 5-124 Known Limitations on page 5-127

5.1

Introduction to Sequences

Sequences let you dene streams of data items sent to a DUT (or streams of actions performed on a DUT interface). You can also use sequences to generate static lists of data items with no connection to a DUT interface. For dening sequences, it is also necessary to dene standard interfacing entities between the sequence and the DUT. Therefore, the sequence solution deals with three main entities: Item A struct that represents the main input to the DUT (for example, packet, transaction, instruction). Typically, such items already exist in your environment, and only very small modication is required to use them with sequences. A struct that represents a stream of items signifying a high-level scenario of stimuli. This is done by generating items one after the other, according to some specic rules. The sequence struct has a set of predened elds and methods. The sequence struct can also be extended by the user.

Sequence

5-2
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Introduction to Sequences

Sequence Driver

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

To complete the picture:

A TCM does the actual driving of items into a specic DUT channel. The TCM resides in a BFM unit. For the purpose of driving data into the DUT, the sequence driver interacts only with the BFM.
The sequence driver and the BFM work as a pair, where the sequence driver serves as the interface upwards towards the sequences so that the sequences can always see a standard interface to the DUT. The BFM serves as the interface downwards to the DUT, letting you write sequences in any way you nd appropriate. At rst, it might seem unnecessary to separate the sequence driver and the BFM. The importance of this separation becomes clear when implementing virtual sequences (see Using Virtual Sequences on page 5-23).
Figure 5-1 describes the general ow of data and control in sequences.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-3

Sequences: Constructing Test Scenarios


How to Use Sequences in Your Environment

Figure 5-1 Flow of Control and Data in Sequences


TX Agent Cong: ... Sequence Driver
seq seq

Fields: Sequence Item


id kind == TX backpointer

...

Clock Event
seq seq seq

Signal Map

Mon DUT

BFM

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

The sequence driver launches the main TCM of a sequence (called body()), which in turn launches
the main TCM of any subsequences. (See Dening the Behavior of Sequences on page 5-12.)

Sequences generate items on the y (as part of the execution of their body() TCM). Each generated item is passed to the sequence driver, which in turn passes it to the BFM.
Note All of the above actions are done automatically by the sequence mechanism. The subsequence and item actions are encapsulated in the new do action. (See Activating Items and Subsequences on page 5-13.)

5.2
1. 2. 3.
5-4

How to Use Sequences in Your Environment

To use sequences in your environment: Dene the sequence item struct. Dene the sequence and its driver using the sequence statement. Hook the sequence driver to the environment.
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

Sequences: Constructing Test Scenarios


Getting Started with Sequences

4. 5.

Create your sequence library by implementing various scenarios using the sequence struct. Write tests based on the sequence library.

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

See Also For more information on Step 1 through Step 3, see Getting Started with Sequences on page 5-5 For more information on Step 4, see Implementing Sequences on page 5-11 For more information on Step 5, see Writing Tests Using Sequences on page 5-18

5.3

Getting Started with Sequences

This section describes how to dene sequences in your environment and hook them to your BFM. This section includes:

Dening the Sequence Item on page 5-5 Dening the Sequence and Its Driver Using the sequence Statement on page 5-5 Hooking the Sequence Driver to the Environment on page 5-9

5.3.1

Dening the Sequence Item

For an item to be used with sequences it must have some common functionality. Therefore, dene the item struct like you always do but inherit from the predened type any_sequence_item. For example:
struct ex_atm_cell like any_sequence_item { kind: [A1, A2, A3, A4]; color: ex_atm_color; .. };

Note If you have a pre-existing environment that does not use sequences, you must edit the basic item to make it inherit as above.

5.3.2

Dening the Sequence and Its Driver Using the sequence Statement

Dene the sequence struct and the sequence driver unit using the sequence statement.
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-5

Sequences: Constructing Test Scenarios


Dening the Sequence and Its Driver Using the sequence Statement

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

Options
item = item_type The item to be used in the sequence. This item must be already dened and inherits from any_sequence_item. The item struct is extended by the sequence statement. If the item option is not used, then this is assumed to be a virtual sequence (see Using Virtual Sequences on page 5-23). created_kind = kind_name created_driver = driver_name sequence_type = base_sequence_name The name of the associated kind enumerated type to be created (default: sequence_name_kind). The name of the associated sequence driver to be created (default: sequence_name_driver). The name of the sequence struct your sequence inherits from (default: any_sequence). For more information, see Creating a Common Base for Your Sequences and Sequence Drivers on page 5-49. sequence_driver_type = base_sequence_driver_name The name of the sequence driver unit your sequence driver inherits from (default: any_sequence_driver). For more information, see Creating a Common Base for Your Sequences and Sequence Drivers on page 5-49.

Example 1

Dening a BFM sequence for ATM cells

sequence ex_atm_sequence using item=ex_atm_cell;

This statement assumes that an ex_atm_cell struct already exists. It denes: Struct Type Unit ex_atm_sequence (inherits from any_sequence) ex_atm_sequence_kind ex_atm_sequence_driver (inherits from any_sequence_driver)

Example 2

Defining a virtual sequence for an SoC environment

sequence soc_sequence;

This statement denes the soc_sequence struct, the soc_sequence_kind type, and the soc_sequence_driver unit.
5-6
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Dening the Sequence and Its Driver Using the sequence Statement

For more information about virtual sequences, see Creating a Virtual Sequence on page 5-24. The rest of this section describes the entities that the sequence statement creates or extends:

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

5.3.2.1

Sequence Struct

The sequence statement creates a new sequence struct (ex_atm_sequence in Example 1 on page 5-6), which inherits from the predened any_sequence, which in turn inherits from any_sequence_item. The main members of the created sequence struct are: driver: driver_name; kind: kind_name; body() @driver.clock is empty; parent_sequence: sequence_name; Reference to the sequence driver For creating sequence subtypes with various behavior Denes the sequence behavior to be implemented by the user Backpointer to the creating sequence of the sequence. Assigned automatically in pre_generate() of the sequence if such a parent exists

Note The only way to dene sequences is via the sequence statement; however, you can dene a base sequence by deriving it from any_sequence. For more information see Creating a Common Base for Your Sequences on page 5-49. For the full list of the sequence struct members, see any_sequence Interface on page 5-111.

5.3.2.2

Sequence Driver Unit

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

The main members of the created driver unit are:

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-7

Sequences: Constructing Test Scenarios


Dening the Sequence and Its Driver Using the sequence Statement

sequence: MAIN sequence_name; event clock; get_next_item(): item_name @clock event item_done

The MAIN sequence, whose body is started automatically at the beginning of the run phase Main clock for the sequences (to be implemented by the user) Method used to get the next item to be created by the sequences Event emitted to inform the sequence driver that the BFM is ready for the next item

Notes

Some of the above methods apply only for BFM sequence drivers and not for virtual sequence drivers.
For more information about virtual sequences, see Using Virtual Sequences on page 5-23.

The only way to dene sequence drivers is via the sequence statement; however, you can dene a
base sequence driver by deriving it from any_sequence_driver. For more information, see Creating a Common Base for Your Sequence Drivers on page 5-50.

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

5.3.2.3

Item Struct

The sequence statement does not create the item struct, but it extends it. The main members that are added to the item struct are: driver: driver_name; parent_sequence: sequence_name; Reference to the sequence driver that facilitates the actual driving to the DUT Backpointer to the creating sequence of the item. Assigned automatically in pre_generate() of the item

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

5.3.2.4

Sequence Kind Type

The sequence statement creates a new kind enumerated type called sequence_name_kind (ex_atm_sequence_kind in Example 1 on page 5-6), which has the following predened values:
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-8

Sequences: Constructing Test Scenarios


Hooking the Sequence Driver to the Environment

MAIN

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

RANDOM SIMPLE

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

See Also Predened Sequence Kinds on page 5-117

5.3.3
1. 2. 3. 4. 5.

Hooking the Sequence Driver to the Environment

To hook the sequence driver into your environment: Add a reference to the sequence driver in the BFM. Instantiate the sequence driver in the environment. Connect the sequence drivers clock to the BFMs clock. Transfer the item from the driver to the BFM by adding a TCM that explicitly requests items from the driver and calls the appropriate BFMs TCM. (Optional) Add useful elds and methods to the base sequence type.

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

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-9

Sequences: Constructing Test Scenarios


Hooking the Sequence Driver to the Environment

};

Have a BFM that knows how to drive a cell into the DUT:
unit ex_atm_bfm { event a_clock is rise('atm_clk') @sim; // ATM main clock drive_cell(cell: ex_atm_cell) @a_clock is { // drives cells to the DUT ... }; };

The BFM is instantiated in an ATM verication environment:


unit ex_atm_agent { bfm: ex_atm_bfm is instance; };

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

Then hook the sequence into the environment:


// 1. Add a reference to the sequence driver in the BFM extend ex_atm_bfm { driver: ex_atm_driver; }; // 2. Instantiate the sequence driver in the ATM environment extend ex_atm_agent { driver: ex_atm_driver is instance; keep bfm.driver == driver; }; // 3. Connect the (predefined) clock event to the BFM's clock extend ex_atm_bfm { on a_clock { emit driver.clock; }; }; // 4. Pull item from driver, process it, then inform using item_done extend ex_atm_bfm { execute_items() @clock is { var seq_item: ex_atm_cell; while TRUE { seq_item = driver.get_next_item();
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-10

Sequences: Constructing Test Scenarios


Implementing Sequences

drive_cell(seq_item); emit driver.item_done; }; }; run() is also { start execute_items(); }; };

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

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

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

The execute_items() TCM of the BFM pulls the items created by the sequences and drives them into
the DUT using the drive_cell() TCM.

After each item is driven to the DUT, the event driver.item_done is emitted to let the sequence
complete the do action and inform the driver that the item was processed. Note If your verication environment contains several ex_atm_unit instances, each of them will have a sequence driver and hence a MAIN sequence and a random stream.

See Also BFM-Driver Interaction Mode on page 5-43

5.4

Implementing Sequences

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

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-11

Sequences: Constructing Test Scenarios


Implementing a Scenario Using the Sequence Struct

Implementing a Scenario Using the Sequence Struct on page 5-12 Creating a Sequence Library on page 5-17

5.4.1

Implementing a Scenario Using the Sequence Struct

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

Dening the Behavior of Sequences on page 5-12 Activating Items and Subsequences on page 5-13 Using Sequences from a rst of Block on page 5-13 Parameterizing Sequences on page 5-15 Enhancing the User Interface on page 5-15

5.4.1.1

Defining the Behavior of Sequences

The body() TCM is a predened TCM of any_sequence that is implemented to dene the behavior of the sequence. The body() TCM of the MAIN sequence that is generated directly under the sequence driver is launched automatically by the run() method of the sequence driver. The body() of any subsequence is activated by the do action. The body() TCM denes the life cycle of the sequence and, as such, denes the duration of the sequences. Before body() is initiated, the predened event started occurs. When body() is nished, the predened event ended occurs. You cannot call or start body() directly. Instead, use the following: To call the body() TCM:

Use the do action.


For example:
do sequence;

To start the body() TCM:

Use the any_sequence predened method start_sequence().

5-12
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Implementing a Scenario Using the Sequence Struct

For example:
sequence.start_sequence();

Note The do action can be used only within a sequence TCM. For details about the additional effects of the do action, see Activating Items and Subsequences on page 5-13. Except for the aforementioned restriction, body() is just a normal TCM. You can use ordinary procedural code in it, and you can extend it using is rst, is also, or is only. When starting the body() TCM using the start_sequence(), there are two hooks, pre_body() and post_body() TCMs, that can be used as follows: pre_body() This lets you do any actions (time-consuming or non-time-consuming) prior to execution of body() and, if need be, prevent the execution of body() by calling the stop() method. This lets you do any actions (time-consuming or non-time-consuming) after the execution of body().

post_body()

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

5.4.1.2

Activating Items and Subsequences

To activate an item or a subsequence from within a sequence:

Use the do action. See Also do on page 5-95 do_and_grab on page 5-97

5.4.1.3

Using Sequences from a first of Block

When using a do action in a rst of branch, the do action might terminate prematurely if a different branch concludes rst. Table 5-1 describes the way the sequence mechanism handles the situation, depending on the state of the do action. Table 5-1 Handling of Premature Termination of do Action State of do Action Waiting for scheduling
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

Description of Behavior The sequence driver will not schedule this do action.

5-13

Sequences: Constructing Test Scenarios


Implementing a Scenario Using the Sequence Struct

Table 5-1 Handling of Premature Termination of do Action State of do Action In pre_do() Description of Behavior The sequence driver will not be able to schedule another do action during the current cycle. Normal operation resumes in the next cycle. You can enable resumption of normal operation in the current cycle by calling the method any_sequence_driver.branch_terminated() after the rst of completes. After pre_do() and item generation The sequence driver will return the item (if not already returned). Normal operation resumes after emitting item_done.

Note Table 5-1 is relevant only when the do action applies to an item. When the do action applies to a sequence rather than an item, no interaction with the driver is involved. When calling a get/try_next_item() method in a rst of branch, the method might terminate prematurely if a different branch concludes rst. Table 5-2 describes the way the sequence mechanism handles the situation, depending on the state of get/try_next_item(). Table 5-2 Handling of Premature Termination of get/try_next_item() State of get/try_next_item() Driver has not yet chosen a do action Driver already chose a do action but get/try_next_item() did not return yet Notes Description of Behavior Nothing happens (as if there was no call to get/try_next_item()). Chosen do action is discarded (even if the item is already generated). The sequence continues to run (as if the do nished normally).

When working with a layered protocol, a get/try_next_item() method might be called as a result of
a do action from another layer. That do action might also be inside a rst of, in which case the get/try_next_item() would also be inside the rst of.

When a rst of branch calling get/try_next_item() is terminated after the item is received,
driver.item_done must still be emitted.

5-14
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Implementing a Scenario Using the Sequence Struct

5.4.1.4

Parameterizing Sequences

Cadence recommends representing any specic behavior of the sequence by a eld so that the value of the eld is the parameter for the specic feature in the sequence behavior. For example, if your sequence creates items in a loop, then the number of iterations of the loop is a typical parameter. These parameters can be viewed as the public interface of the sequence. In this way, you can later control the parameters using constraints from the outside without knowing the actual implementation of body(). For example, consider the predened RANDOM sequence:
extend RANDOM ex_atm_sequence { count: uint; !sequence: ex_atm_sequence; body() @driver. clock is { for i from 1 to count { do sequence; }; }; };

The parameter of this sequence is count, which is the number of random sequences that will be created by the sequence. You can control the behavior of all RANDOM sequences in the environment by constraining the count:
extend RANDOM ex_atm_sequence { keep count in [10..20]; };

Note Such a constraint can also be applied locally to a RANDOM sequence eld in another sequence or even in a specic do.

5.4.1.5

Enhancing the User Interface

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

Using Methods
In the sequence struct, you can dene methods that encapsulate a typical do action. An example is a read/write interface. For example, assume that a bus-based design with the basic item c_bus_op is dened as follows:

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-15

Sequences: Constructing Test Scenarios


Implementing a Scenario Using the Sequence Struct

struct c_bus_op like any_sequence_item { kind: [READ, WRITE, OTHER]; address: int; color: [RED, GREEN, WHITE]; when WRITE c_bus_op { data: int; // Sent data }; when READ c_bus_op { !data: int; // Returned data }; };

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


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

But sometimes it is more convenient to write something like:


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

To do that, dene methods in the corresponding sequence that implement these operations:
extend ex_c_bus_sequence { !write_op: WRITE c_bus_op; !read_op: READ c_bus_op; // Do a c_bus write write(address: int, data: int) @driver.clock is { do write_op keeping {.address == address; .data == data}; }; // Do a c_bus read // NOTE: The read operation returns a value to the sequence. This // requires additional infrastructure in the send_to_bfm() method to // ensure that the data on the operation will be valid after the do // action. read(address: int): int @driver.clock is { do read_op keeping {.address == address}; return read_op.data; }; };

This lets you use the convenient procedural interface while still keeping the ability to constrain other elds (such as c_bus_op.color) from the outside. For more information about a read/write interface, see DUT-Independent Read/Write Interface on page 5-39.

5-16
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Creating a Sequence Library

Using Macros
Sometimes, you might need the greater syntactical exibility that only macros can afford. In that case, Cadence recommends creating action macros that implement typical do actions. For example:
define cell'action "cell <len'num> <kind'name>[ <x'num>]" as { do cell keeping { .len == <len'num>; .kind == <kind'name>; .x == <x'num|0>; }; };

Then you can write shorthand like:


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

5.4.2

Creating a Sequence Library

Once you dene the sequence struct, you can create various scenarios (sequence kinds) by creating subtypes of the sequence using the kind eld. Each kind of sequence can implement a typical scenario or a combination of existing scenarios. The set of sequence kinds is the sequence library. Cadence recommends dening the sequence library in a separate le or les that can be loaded on top of the environment. This lets you include or exclude some of the sequence kinds upon demand of specic tests. Note The term subtype applies when creating a new type using when inheritance. To create a sequence library: 1. Extend the sequence kind type with the desired new kind. For example:
extend ex_atm_sequence_kind: [SHORT_LONG];

2.

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

New parameters New implementation of body()

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-17

Sequences: Constructing Test Scenarios


Writing Tests Using Sequences

Any other struct members such as constraints, methods, and so on


For example:
extend SHORT_LONG ex_atm_sequence { // new parameter short_count: int [1..8]; // number of short cells in sequence // New implementation of body() body() @driver.clock is { for i from 1 to short_count do { do cell keeping {.len <= 2}; }; do cell keeping {.len == 5}; }; };

Note Cadence recommends encapsulating any meaningful scenario as a new sequence kind. 3. Iterate Step 1 and Step 2 as required.

5.5

Writing Tests Using Sequences

After dening sequences and implementing several subtypes in the environment, it is time to use them. As a sequence models the input stream of an agent, it becomes the common interface for writing tests. Cadence recommends using sequences in tests to create a sequence library by dening many subtypes of sequences based on the kind eld of the sequence. (See Creating a Sequence Library on page 5-17.) Then create tests that use these subtypes by parameterizing them, enhancing them, or using them as is with some weights. In some simple cases you can avoid dening new sequence kinds altogether by directly redening the body() method of the MAIN sequence. Alternatively, you can dene a specic new sequence kind directly in the test and then use it. This section demonstrates all of the above options. This section includes:

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

5-18
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Writing the Simplest Test: Redening MAIN Sequence body()

5.5.1

Writing the Simplest Test: Redening MAIN Sequence body()

The simplest way to write tests is to redene the behavior of the MAIN sequence by overriding its body() method. This is sufcient to create a test, because the MAIN sequence is started automatically as part of the infrastructure of sequences and so there is no need to handle that in the test. This approach is useful for creating simple directed tests.

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

5.5.2

Writing a Typical Test: Using the Sequence Library

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

Writing a Random Test: Setting Weights on page 5-19 Modifying an Existing Sequence on page 5-20

5.5.2.1

Writing a Random Test: Setting Weights

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

Example
extend MAIN ex_atm_sequence { keep soft sequence.kind == select { 30: ALTERNATING_COLOR; 60: SHORT_LONG; 10: FIXED_LEN; };
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-19

Sequences: Constructing Test Scenarios


Writing a Typical Test: Using the Sequence Library

};

5.5.2.2

Modifying an Existing Sequence

Often, using the existing kinds is not sufcient. Sometimes it is enough to just apply additional constraints on the sequence parameters, but sometimes you want to introduce somewhat different behavior (for example, waiting three more cycles) into an existing sequence. The way to modify an existing sequence is to extend the sequence subtype in the test itself.

Example
// Modify the behavior of FIXED_LEN sequence - wait additional 3 cycles // after it ends extend FIXED_LEN ex_atm_sequence { body() @driver.clock is also { wait [3] * cycle; }; }; // Use the (modified) kind in the test extend MAIN ex_atm_sequence { keep soft sequence.kind == select { 60: SHORT_LONG; 40: FIXED_LEN; }; };

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

5-20
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Writing a Dedicated Test: Creating a New Sequence Kind

body() @driver.clock is also { wait [3] * cycle; }; }; // Use the (modified) kind in the test. extend MAIN ex_atm_sequence { keep soft sequence.kind == select { 60: SHORT_LONG; 40: FIXED_LEN; }; };

Note This is very modular, even though an existing sequence is extended inside a le describing another sequence.

5.5.3

Writing a Dedicated Test: Creating a New Sequence Kind

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

You do not intend to use the sequence in any other test. You do not want to expose the environment to this sequence (to avoid random sequences using this
kind occasionally). To dene a sequence kind in a test, use the same methodology recommended in Creating a Sequence
Library on page 5-17.

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

5.5.4

Writing a Unit-Related Test: Using Unit ID

Cadence recommends that units have ID elds associated with their roles within the parent unit. These ID elds can be enumerated types (for example, ex_atm_name) or numbers (for example, agent_num). In effect, these elds correspond to the role the eld is playing. For example, you can add to your environment a code similar to this:
type ex_atm_env_name: [NORTH, SOUTH]; extend ex_atm_env { name: ex_atm_env_name; }; unit comm_env {
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-21

Sequences: Constructing Test Scenarios


Writing a Unit-Related Test: Using Unit ID

north_atm: NORTH ex_atm_env is instance; south_atm: SOUTH ex_atm_env is instance; ethernet_ports: list of ethernet_port is instance; keep for each in ethernet_ports {.ind == index}; };

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

Once such IDs exist, you can use methods like those mentioned in Propagating Parameters in the Sequence Tree on page 5-31 and Migrating Unit Attributes to the Sequences on page 5-32 to apply the IDs to the sequences themselves. Note The name NORTH ex_atm_env species a role of ex_atm_env, sometimes mistakenly called an instance. This section includes:

Unit IDs to Constrain Sequences on page 5-22 Hierarchical Unit IDs on page 5-22

5.5.4.1

Unit IDs to Constrain Sequences

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

5.5.4.2

Hierarchical Unit IDs

Use hierarchical IDs when roles are not unique throughout the DUT. For example, you could dene an SoC containing four comm_envs as follows:
unit SoC { comm_envs[4]: list of comm_env; keep for each in comm_env {.index == index};
5-22
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Sequence File Organization

};

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

5.6

Sequence File Organization

Typically, sequence implementation is split into several les: Sequence denition les DUT-specic sequence hook le Sequence libraries Test les Dene a sequence for a specic item (packet, transaction, and so on) in any environment Extends the sequence for use with a specic DUT and hooks the sequence to the environment Dene various sequence subtypes that implement specic scenarios, either generic or DUT-specic Import relevant sequence libraries and use them

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

See Also Chapter 3 eVC File Organization

5.7

Using Virtual Sequences

BFM sequences are tightly connected to their own type and items. In other words, BFM sequences can only do sequences of their own type or items of the type specied in the sequence statement. BFM sequences cannot do sequences created by other sequence statements. Virtual sequences, unlike BFM sequences, are not tightly connected to a specic sequence type or item. Virtual sequences can do sequences of other types (but not items). As a result, you can use virtual sequences to:
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-23

Sequences: Constructing Test Scenarios


Creating a Virtual Sequence

Drive more than one agent Model a generic driver


A virtual sequence is driven by a virtual sequence driver, which typically has references to the individual BFM sequence drivers. Virtual sequences can be used to synchronize and dispatch BFM sequences to several BFM drivers. A virtual sequence driver is not connected to a specic BFM. Therefore, it lacks the logic and functionality of a BFM driver. For example, a virtual sequence driver does not schedule itemsit only drives sequences. As much of the driver functionality is aimed at controlling and manipulating the scheduling of items, any method that controls this functionality cannot be called for a virtual sequence. For example, you cannot grab/ungrab a virtual sequence driver, because grabbing manipulates the scheduling of items. For a full list of driver interface methods that cannot be used for virtual drivers, see Table 5-17 on page 5-113. The following sections describe how this is done. See also ex_soc_1_sequences.e in the ex_soc/e directory, or just load ex_soc_1_test.e (in the ex_soc/examples directory) and run it. This section includes:

Creating a Virtual Sequence on page 5-24 Passing of Sequence Drivers on page 5-26 Making Other Sequence Drivers Behave on page 5-26 Sequences for SoC on page 5-27 Transactions on page 5-29

5.7.1
1.

Creating a Virtual Sequence

To create a sequence that controls several sequence drivers: Dene a virtual sequence with a corresponding virtual sequence driver. For example:
sequence comm_sequence; // Note no "item=" option

2.

Add elds to the virtual sequence driver that point to the subdrivers. For example:
extend comm_sequence_driver { atm: ex_atm_master_sequence_driver;

5-24
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Creating a Virtual Sequence

ethernet: ethernet_sequence_driver;

3.

Dene the get_sub_drivers() method to return the subdrivers. For example:


get_sub_drivers(): list of any_sequence_driver is { return {atm; ethernet}; }; };

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

4.

Dene the sequence driver in the appropriate unit in your environment (probably the lowest unit enclosing all of the component drivers). For example:
extend comm_subsystem_unit { driver: comm_sequence_driver is instance; // Constrain the subdrivers. keep driver.atm == atm1_unit.driver; keep driver.ethernet == ethernet_router_unit.driver; };

The sequence driver will launch under its MAIN comm_sequence. 5. Dene a clock for the sequence driver. For example:
extend comm_sequence_driver { event clock is only @sys.any; };

Notes

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

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-25

Sequences: Constructing Test Scenarios


Passing of Sequence Drivers

5.7.2

Passing of Sequence Drivers

By default, the driver of a called sequence (including the driver of an item that is created within a sequence) is the driver of the calling sequence. This is enforced via a soft constraint. However, when a virtual sequence is do-ing a BFM sequence, it must pass the appropriate subdriver to the BFM sequence. To pass a sequence driver for a sequence:

Constrain the sequence driver in the keeping block of the do action.


For example:
do RWR ex_atm_sequence keeping {.driver == driver.atm};

5.7.3

Making Other Sequence Drivers Behave

Suppose you create a virtual sequence driver that controls two subdrivers (as in the ex_soc_1_sequence.e le). How do you want the subdrivers to behave while your new, virtual sequence driver is also sending them items? There can be three main answers:

Business as usual:
You want the virtual sequence driver and the original sequence drivers to work at the same time, using the built-in capability of the original sequence drivers. This is the default behavior. There is no need to do anything to achieve this.

Disable the subdrivers:


This is most simply achieved as follows (taken from ex_soc_1_test.e):
extend MAIN ex_atm_sequence { keep count == 0; }; extend MAIN ex_c_bus_sequence { keep count == 0; };

Setting the count to 0 means these MAIN sequences will return immediately. Note Alternatively, you can override the body() TCM of the MAIN sequence to do nothing as follows:
extend MAIN ex_c_bus_sequence { body() @driver.clock is only {};
5-26
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Sequences for SoC

};

Use grab() and ungrab():


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

5.7.4

Sequences for SoC

SoC environments typically require synchronization of the input of several agents, as illustrated in Figure 5-2 on page 5-27. Figure 5-2 eVCs within SoC Design
SD Mon BFM

Virtual Sequence

SD Mon BFM

Memory Controller CPU Bus

DMA Controller

Bridge Peripheral Bus

System Chip

UART

GPIO

USB

Ethernet

SD Mon BFM

SD Mon BFM

SD Mon BFM

SD Mon BFM

To control a multiple-agent environment: 1. 2. Ensure that each of the agents has its own sequence (and sequence driver). Dene a new (virtual) sequence (and sequence driver) using the sequence statement and omitting the item parameter.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-27

Sequences: Constructing Test Scenarios


Sequences for SoC

3. 4.

Add the existing sequence drivers as elds of the new sequence driver. Pass the existing sequence drivers using constraints to the BFM sequences done by the virtual sequence.

SoC Sequence Example


sequence comm_sequence; // Note no "item=" option extend comm_sequence_driver { atm_driver: ex_atm_master_sequence_driver; eth_driver: ethernet_sequence_driver; }; extend comm_subsystem_unit { driver: comm_sequence_driver is instance; keep driver.atm_driver == ex_atm_unit.driver; keep driver.eth_driver == ethernet_unit.driver; }; extend MAIN comm_sequence { !atm_sequence: ex_atm_sequence; !eth_config: ethernet_sequence; body() @driver.clock is only { do eth_config keeping {.driver == driver.eth_driver}; do atm_sequence keeping {.driver == driver.atm_driver}; }; }; extend MAIN ex_atm_sequence { keep count == 0; };Figure 5-3 on page 5-29 demonstrates the above example.

5-28
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Transactions

Figure 5-3 SoC Sequence Example


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

Virtual Driver
eth_cong seq atm_sequence

atm_env ATM Sequence Driver

eth_env Ethernet Sequence Driver


seq seq

seq

seq

seq

BFM

BFM

5.7.5

Transactions

The term transaction includes both items and sequences. In an SoC context, there can be DMA transactions, MPEG transactions, and so on. Such transactions normally consist of writing to several registers to initialize the DMA or MPEG device and possibly sending an MPEG input packet to the MPEG input channel, either in parallel or after writing to all of the registers. It is easiest to package the transaction as a virtual sequence. Then you can have a higher-level sequence go as follows:
do sequence keeping {.kind == DMA_TRANS}; do sequence keeping {.kind == MPEG_TRANS};

5.8

Advanced Generation-Related Aspects of Sequences

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

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-29

Sequences: Constructing Test Scenarios


Specifying Subtype in do Actions

This section contains:

Specifying Subtype in do Actions on page 5-30 Propagating Parameters in the Sequence Tree on page 5-31 Migrating Unit Attributes to the Sequences on page 5-32 Generating the Item/Sequence in Advance on page 5-33 Constraining Complex Sequence Items on page 5-33

5.8.1

Specifying Subtype in do Actions

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

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

Syntax for Specifying Subtype in do Actions


do when-determinant1n eld [keeping { it. };]

Parameters
when-determinant1n eld Must be when determinants of the declared type of the eld. The sequence or item

Note it already refers to the subtype. There is no need for casting to access the subtype attributes.

Example 1
extend MAIN my_sequence { seq: my_sequence; body() @driver.clock is { do RED seq keeping { it.red_level == 10 }; do GREEN seq keeping {
5-30
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

// Access red_level without casting

e Reuse Methodology

Sequences: Constructing Test Scenarios


Propagating Parameters in the Sequence Tree

.green_level == 18; }; do ATOMIC GREEN seq keeping { it.green_level == 12; it.atomic_level == PARTIAL; }; do YELLOW seq ; }; };

Example 2
extend MAIN my_sequence { !seq: GREEN my_sequence; body() // // do @driver.clock is { seq will be generated to LONG GREEN my_sequence (not GREEN LONG order does matter). LONG seq keeping { it.length > 10; // length is a field of LONG

}; // seq will be generated to ATOMIC GREEN my_sequence do ATOMIC seq keeping { it.green_level == 12; it.atomic_level == PARTIAL; }; }; };

5.8.2

Propagating Parameters in the Sequence Tree

Sometimes you must propagate the value of a sequence parameter (for example, unit ID) down the sequence tree so that the root sequence (for example, the MAIN sequence) is assigned a specic value. This value then propagates automatically to all sequences generated using do anywhere along the hierarchy underneath the root sequence. To propagate parameters down the sequence tree: 1. 2. Add the parameter to the base sequence type. Use the predened eld parent_sequence to propagate the value. For example:
keep parent_sequence != NULL => soft my_param == parent_sequence.as_a(ex_atm_sequence).my_param;

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-31

Sequences: Constructing Test Scenarios


Migrating Unit Attributes to the Sequences

3.

Add an additional constraint for the root sequence in the root-sequence parent.

Example
type ex_atm_port_id: [ATM_0, ATM_1]; extend ex_atm_sequence { port_id: ex_atm_port_id; // Field to be propagated keep parent_sequence != NULL => // The propagating constraint soft port_id == parent_sequence.as_a(ex_atm_sequence).port_id; }; extend ex_atm_driver { port_id: ex_atm_port_id; keep sequence.port_id == port_id; };

// Constrain sequence root in driver

5.8.3

Migrating Unit Attributes to the Sequences

It is often good methodology to migrate unit names and attributes to corresponding sequences. To migrate unit names and attributes to corresponding sequences: 1. 2. Dene a eld in the sequence struct to represent the unit attribute. Migrate the value from the unit using get_enclosing_unit().

Example
extend ex_atm_sequence { // 1. Define the unit name in the sequence. name: ex_atm_name; // 2. Migrate the value from the enclosing unit. keep name == get_enclosing_unit(ex_atm_agent).name; };

Then you can say things like:


extend NORTH MAIN ex_atm_sequence { ... };

This is a useful shorthand. Nevertheless, you might still need to reference the IDs of the enclosing units if you want a more complete hierarchical identication.

5-32
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Generating the Item/Sequence in Advance

5.8.4

Generating the Item/Sequence in Advance

Sometimes you might want to generate or instantiate the item or sequence before the do action. You could then use the instantiated item or sequence in the do action without regenerating it. To generate/instantiate the item/sequence in advance: 1. 2. 3. Dene an additional eld/variable of the same type as the item/sequence. Either generate the eld/variable using the gen action or instantiate it using the new action. Constrain the eld in the do action to be equal to the additional eld/variable (dened in Step 1).

For example:
extend FOO ex_atm_sequence { // Items/subsequences !cell: ex_atm_cell; // The body() method body() @driver.clock is { var preprepared_cell: ex_atm_cell; gen preprepared_cell; ... do cell keeping {it == preprepared_cell}; }; };

To return immediately (non-blocking do), implement the method that processes the item to be non-time-consuming and return immediately.

5.8.5

Constraining Complex Sequence Items

Constrain complex sequence items when Suppose you have a data item that contains a list with items that you want to constrain. In this case, you cannot use the it variable to refer to the list items, because it already refers to the data item itself. Instead, you must specify a new name for the list items. In the following example, the name item is used for this purpose.
extend NEW my_sequence { body @driver.clock is only { do burst keeping { .addr <= 1000; .type in [READ, WRITE]; for each (data_item) in .data {

// Specify name for list item

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-33

Sequences: Constructing Test Scenarios


Implementing Complex Scenarios

data_item > 10 and data_item < 90; }; }; }; };

5.9

Implementing Complex Scenarios

This section contains:

Dening Concurrent Sequences on page 5-34 Initializations and Congurations before Starting Sequences on page 5-35 Interrupt Sequences on page 5-36 Resetting and Rerunning Sequences on page 5-37 DUT-Independent Read/Write Interface on page 5-39 Controlling the Scheduling of Items on page 5-42 Locking of Resources on page 5-43 BFM-Driver Interaction Mode on page 5-43 Handling Pipelined Protocols on page 5-45

5.9.1

Dening Concurrent Sequences

You can create concurrent sequences in two ways:

Using the do action within an all of block Starting several sequences using the start_sequence() method Example 1 Using the do action

In this example, the number of sequences is determined statically.


// Do multiple SHORT_LONG sequences in parallel extend ex_atm_sequence_kind: [PARALLEL_3]; extend PARALLEL_3 ex_atm_sequence { !sl_seq: SHORT_LONG ex_atm_sequence; body() @driver.clock is { all of { {do sl_seq keeping {.short_count == 1}}; {do sl_seq keeping {.short_count == 2}};
5-34
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Initializations and Congurations before Starting Sequences

{do sl_seq keeping {.short_count == 3}}; }; }; };

Example 2

Starting several sequences in parallel

In this example, the PARALLEL_N sequence activates n sequences in parallel. It does not wait for the sequences to complete, but immediately nishes after activating the sequences.
// Do multiple SHORT_LONG sequences in parallel extend ex_atm_sequence_kind: [PARALLEL_N]; extend PARALLEL_N ex_atm_sequence { // num_of_sequences can be constrained from above num_of_sequences: int; keep soft num_of_sequences == 3; // The list of sequences to activate sl_seq_l: list of SHORT_LONG ex_atm_sequence; keep sl_seq_l.size() == num_of_sequences; keep for each in sl_seq_l { it.driver == driver; }; body() @driver.clock is { for each (seq) in sl_seq_l { it.start_sequence(); }; }; };

Note The number of sequences that PARALLEL_N activates can be controlled by a higher-level sequence.

5.9.2

Initializations and Congurations before Starting Sequences

The sequence driver generates the MAIN sequence and starts its body() method upon run(). Sometimes you might want to perform some operations before starting to randomize the sequences. For example, a test might start with a conguration stage and an initialization stage before the actual testing starts. You can implement these preliminary stages of the test with sequences. For example:
extend MAIN ex_atm_sequence { body() @driver.clock is only { do initialization_sequence;

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-35

Sequences: Constructing Test Scenarios


Interrupt Sequences

... }; };

Another way to perform initializations before the test is by extending the pre_body() method to delay the execution of body(). For example:
extend MAIN ex_atm_sequence { pre_body() @sys.any is { // Perform configuration configure_dut(); // Wait until initialization is done sync true(driver.initialization_done); }; };

5.9.3

Interrupt Sequences

Many environments include an interrupt option. Typically, an interrupt occurrence should be coupled with some reaction from the agent. Once the interrupt is done, you can consider either aborting any previous activity or continuing it from the point where it stopped. All of this can be supported using sequences. To handle interrupts using sequences: 1. Dene an interrupt sequence that implements the reaction-upon-interrupt scenario, including: a. b. c. d. e. 2. 3. Wait for the interrupt event to occur (that is, serves as the interrupt handler). Grab the sequence driver for exclusive access. (Optional) Stop the activity of the other existing sequences. Execute the interrupt scenario. Ungrab the sequence driver.

Instantiate the interrupt sequence under the sequence driver. Start the interrupt sequence in the run() method of the sequence driver.

Example
(Taken from ex_interrupt_abort_test.e in the ex_atm/examples directory.)
// 1. Define an interrupt sequence. extend ex_atm_sequence_kind: [INTERRUPT_ABORT];

5-36
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Resetting and Rerunning Sequences

extend INTERRUPT_ABORT ex_atm_sequence { // Upon interrupt, grab driver, terminate all its main activity, and // send a configuration sequence body() @driver.clock is { sync @driver.interrupt; // Wait for the interrupt event. grab(driver); // Grab the driver. driver.sequence.stop(); // Stop the MAIN sequence activity. do cell keeping {.color == RED}; // Execute the interrupt scenario. do cell keeping {.color == GREEN}; do cell keeping {.color == BLUE}; ungrab(driver); // Ungrab the driver. }; }; extend ex_atm_driver { // 2. Instantiate the interrupt sequence under the sequence driver iseq: INTERRUPT_ABORT ex_atm_sequence; keep iseq.driver == me; // 3. Start the interrupt sequence run() is also { iseq.start_sequence(); }; }; // The test part extend MAIN ex_atm_sequence { keep count == 1; keep sequence is a ALTERNATING_COLOR ex_atm_sequence; };

Note You can make the activity-termination option a parameter of the interrupt sequence. For example, you could have the sequence actually terminate the other activity only if a Boolean ag is set.

5.9.4

Resetting and Rerunning Sequences

Sometimes you might need to re-execute (reactivate) the sequence driver and its sequences. For example, this could happen upon reset of the DUT. All Specman structs have the predened method rerun() for reactivating the struct and re-executing the run() method. There are two typical modes of operation upon reset:

Call quit() upon reset. Then, at the end of the reset, call rerun(). Call rerun() upon reset. Then use the reset-qualied clock for the structs TCM.
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-37

Sequences: Constructing Test Scenarios


Resetting and Rerunning Sequences

For sequence drivers, the following methods support re-execution of sequences: driver.quit() driver.rerun() Calls to quit() for every started sequence under the driver 1. 2. 3. 4. Calls to quit() Resets the runtime data of the driver Resets the runtime data of all started sequences Re-executes the run() method, which by default starts the MAIN sequence

Notes

When calling to rerun(), the driver continues driving items until the end of the cycle. If the driver
was in the middle of do-ing an item at the end of the cycle, then that item might be lost.

When you have a virtual sequence that controls multiple BFM sequence drivers, rerunning any of
the BFM sequence drivers does not terminate the virtual sequence. If the virtual sequence was in the middle of do-ing a BFM sequence that was do-ing an item at the end of the cycle, then that item might be lost but the BFM sequence continues. The following runtime data is reset upon rerun, at the beginning of the next cycle: All do item actions waiting to be performed grab() method This includes do actions initiated by a higher-level virtual sequence that continues to run. In such case, those do item actions are skipped, and the sequence continues to run. If the driver was grabbed by a sequence before the reset, then the grab will be canceled along with the entire queue of sequences waiting to grab the driver. Therefore, a higher-level virtual sequence that grabbed the driver before the reset must regrab it if needed. Sequences that were waiting to grab the driver (that is, were blocked in the grab() method) are released without grabbing the driver. You cannot use last() to retrieve items that were done before the rerun. For more information on last(), see last() on page 5-105.

The list of previously sent items

Any additional actions needed at quit() time can be added to the quit() method of the driver using is also. For example:
extend ex_atm_sequence_driver { quit() is also {
5-38
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


DUT-Independent Read/Write Interface

out("quitting driver", me); }; };

Any additional actions needed at rerun() time can be added to the rerun() method of the driver using is also. For example:
extend ex_atm_sequence_driver { rerun() is also { out("rerunning driver", me); }; };

Sometimes, you might want to regenerate some of the drivers data upon rerun() (before re-executing the drivers run()). You can do that by extending the method driver.regenerate_data(). For example:
extend ex_atm_sequence_driver { regenerate_data() is also { gen sequence; }; };

Notes

The rerun() method performs the following operations: Quits the struct (which causes the termination of all TCMs and TEs). Executes the run() method. Re-initiates all TEs. The rerun() method does not cause an automatic emission of the @item_done event.

5.9.5

DUT-Independent Read/Write Interface

The uniform interface of sequences lets you develop a generic read/write interface that might be applied to many environments and is not related directly to a specic DUT. Such an interface enables development of system-level tests that are suitable for many congurations of the environment. A typical example is a bus-based conguration test that can be executed over multiple buses, for example, a PCI bus as well as an ATM bus. To implement a DUT-independent interface: 1. 2. Dene a virtual read/write sequence that uses a generic low-level sequence driver to execute the low-level read/write transactions. Hook the virtual sequence driver to a specic sequence driver as follows:

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-39

Sequences: Constructing Test Scenarios


DUT-Independent Read/Write Interface

a. b. c.

Instantiate the virtual sequence driver. Connect its low-level sequence driver to a specic sequence driver. Implement the read/write interface methods of the low-level sequence driver. Note The last portion of the step (2c) might be done already as part of the specic environment. See Enhancing the User Interface on page 5-15.

3.

Use the virtual sequence driver in tests.

Note Each of these steps should reside in a separate le (to allow reuse).

Example
(This is from ex_cbus_rw_test.e in the ex_c_bus/examples directory.) 1. Dene a virtual read/write sequence.
sequence config_sequence; extend config_sequence_driver { low_driver: any_sequence_driver; event clock is only @sys.any; // Implement the read/write interface so that it uses the // low-level sequence driver interface. write(address: list of bit, data: list of bit) @clock is { low_driver.write(address, data); }; read(address: list of bit) : list of bit @clock is { result = low_driver.read(address); }; };

2.

Hook up the virtual sequence driver.


extend sys { cbus_env: c_bus_env is instance; // Instantiate the virtual sequence driver. config_driver: config_sequence_driver is instance; // Connect its low-level sequence driver to a specific // sequence driver. keep config_driver.low_driver == cbus_env.driver; };

5-40
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


DUT-Independent Read/Write Interface

// Implement the read/write interface methods of the low-level // sequence driver. extend ex_c_bus_driver { write(address: list of bit, data: list of bit) @clock is { sequence.write(pack(NULL, address), pack(NULL, data)); }; read(address: list of bit) : list of bit @clock is { result = pack(NULL, sequence.read(pack(NULL, address))); }; }; // Make the c_bus MAIN silent. extend MAIN ex_c_bus_sequence { keep count == 0; };

3.

Test Example: A generic (that is, DUT-independent) conguration test.


extend MAIN config_sequence { !w_data: uint(bits:4); !r_data: uint(bits:4); !addr: uint(bits:6); body() @driver.clock is only { gen w_data; gen addr; outf("sending data: %d to address: %x\n", w_data, addr); driver.write(%{addr},%{w_data}); r_data = %{driver.read(%{addr})}; outf("received data: %d from address: %x\n", r_data, addr); }; };

Notes

The test itself has no notion of the actual agent that eventually executes the read/write transactions. A similar approach can be used to develop additional generic actions such as reset. The use of list of bit and packing in the read/write interface of the sequence driver is essential to
prevent dependency on a specic agent or format and a specic bit width.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-41

Sequences: Constructing Test Scenarios


Controlling the Scheduling of Items

5.9.6

Controlling the Scheduling of Items

There might be several sequences do-ing items concurrently, but the driver can only handle one item at a time. So the driver maintains a queue of do actions; and when there is a demand for an item, the driver chooses a single do action to perform from the do actions waiting in the queue. Therefore, when a sequence is do-ing an item, the do action is blocked until the driver is ready to choose it. The scheduling algorithm works on a rst-come-rst-served basis. You can change the algorithm using grab() and is_relevant(). If a sequence is grabbing the driver, the driver will choose the rst do action that satises the following conditions:

It is done by the grabbing sequence or its descendants. The is_relevant() method of the sequence do-ing it returns TRUE.
If no sequence is grabbing the driver, the driver will choose the rst do action that satises the following condition:

The is_relevant() method of the sequence do-ing it returns TRUE.


If there is no do action to choose, then get_next_item() is blocked. The driver will try to choose again (reactivate the scheduling algorithm) when one of the following happens:

Another do action is added to the queue. A new sequence grabs the driver, or the current grabber ungrabs the driver. The method driver.check_is_relevant() is called. (For more information see Forcing a Reevaluation
of the do Action Queue on page 5-54.)

A new cycle begins.


When calling to try_next_item(), if the driver does not succeed in choosing a do action before the time specied by driver.wait_for_sequences() elapses, then try_next_item() returns anyway but with NULL. To control scheduling:

Use is_relevant() to specify a condition for performing a do action.


or

Grab the driver.

5-42
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Locking of Resources

5.9.7

Locking of Resources

Sometimes a sequence might need to lock resources for a while so that temporarily other sequences will not be able to touch them. For example, a divide-by-zero machine instruction sequence might look like this:
extend DVZ inst_sequence { op1_reg: register; op2_reg: register; body() @driver.clock is { do SET_REG inst_sequence keeping {.reg == op1_reg}; ...Do any random sequence not writing to op1_reg do SET_REG inst_sequence keeping {.reg == op2_reg; .value == 0}; ...Do any random sequence not writing to op1_reg or op2_reg do instr keeping { .op == divide; .op1 == op1_reg; .op2 == op2_reg }; ...Release the locking on op1_reg and op2_reg }; };

The question is what to put in the lines starting with the ellipsis .... grab() and ungrab() will not work here. They are useful to grab sequence drivers, not registers. Cadence recommends using either Boolean ags or lockers inside the sequence driver (or inside the unit where the sequence driver resides). Have one ag or locker for every resource that you want to lock (for example, a register that you do not want people to write to).

5.9.8

BFM-Driver Interaction Mode

Hooking the Sequence Driver to the Environment on page 5-9 describes how to hook the sequence

driver into the environment. In the example given, there is a TCM in the BFM that explicitly calls to driver.get_next_item() in order to receive an item. This means that the environment controls when to get an item from sequences. This style of interaction is called PULL_MODE. It is the default mode. Sometimes you might want the sequences to be the initiators so that you do not need to request an item. Instead, when the driver is ready to do an item, there is an implicit call to driver.send_to_bfm(). This style of interaction is called PUSH_MODE. The interaction mode is determined by the value of driver.bfm_interaction_mode, which is constrained by default to PULL_MODE.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-43

Sequences: Constructing Test Scenarios


BFM-Driver Interaction Mode

5.9.8.1

Working in PUSH_MODE

To work in PUSH_MODE: 1. 2. Constrain driver.bfm_interaction_mode to be PUSH_MODE. Implement the driver.send_to_bfm() TCM so that it calls the BFM TCM that drives the item into the DUT.

Table 5-3 PULL_MODE versus PUSH_MODE Example PULL_MODE


extend ex_atm_bfm { execute_items() @clock is { var seq_item: ex_atm_cell; while TRUE { seq_item = driver.get_next_item(); drive_cell(seq_item); emit driver.item_done; }; }; run() is also { start execute_items(); }; };

PUSH_MODE
extend ex_atm_driver { // Set interaction mode keep bfm_interaction_mode == PUSH_MODE; // Transfer the item from the // driver to the BFM: // Add a call to the BFM's TCM in // the sequence driver's // send_to_bfm() send_to_bfm(seq_item: ex_atm_cell) @clock is only { bfm.drive_cell(seq_item); }; };

Notes

In PUSH_MODE, driver.item_done is automatically emitted when driver.send_to_bfm() returns. PUSH_MODE is implemented using PULL_MODE in the following way:
send_loop() @clock is { while TRUE { var seq_item := get_next_item(); send_to_bfm(seq_item); emit item_done; }; };

The BFM interaction mode is a static property of the environment. It must not be modied during
simulation. For more information about the difference between PUSH_MODE and PULL_MODE, compare Figure
5-18 on page 5-122 to Figure 5-19 on page 5-123.
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-44

Sequences: Constructing Test Scenarios


Handling Pipelined Protocols

5.9.9

Handling Pipelined Protocols

In pipelined protocols, data items undergo a number of processing phases. For example, a data transfer might be either in the address phase or in the data phase. In addition, the DUT can handle concurrently multiple data items with each item in a different phase. When implementing pipelined scenarios with sequences some typical problems arise:

How to launch a new data item while the current data item is still being processed How to ensure that the elds of the data item are stable before sampling them
To implement pipelined scenarios: 1. 2. In the appropriate sequence, list the desired series of pipelined do actions. Emit the item_done event when a trigger event in the BFM indicates that a new data item should be sent to the DUT. This releases the current do action and lets the sequence perform the next do action. For example:
extend my_sequence { !trans1 : READ transfer; !trans2 : WRITE transfer; body()@driver.clock is { -- List a series of pipelined do actions do trans1; do trans2; }; }; extend my_bfm { bfm_loop()@clock is { while TRUE { trans = driver.get_next_item(); start put_on_bus(trans); -- Emit the item_done event when the trigger event occurs wait @need_new_item; emit driver.item_done; }; }; };

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-45

Sequences: Constructing Test Scenarios


Handling Pipelined Protocols

If sampling of data items is required, you need a mechanism for detecting when the data-item elds are updated and ready for sampling. In the above example, the sequence can start to do the WRITE burst before the elds of the READ burst are fully updated. To ensure that data-item elds are ready for sampling: 1. 2. Add a Boolean eld to the data item that is set to TRUE when all elds are up to date. Delay sampling of elds with a wait or sync action that is satised when the eld is TRUE.

For example:
extend transfer { -- Add Boolean field !finished : bool; }; extend my_sequence { !trans1 : READ transfer; body()@driver.clock is { do trans1; -- Delay sampling sync true(trans1.finished); sample(trans1); }; };

When sampling of a pipelined data items elds is required immediately after the item is completely processed, then the above approach must be rened. The sampling of each item must occur in a thread distinct from that of the do of the next item. You can achieve this in several ways.

Example 1

Combine do action with associated sampling

extend transfer { -- Add Boolean field !finished : bool; get_data()@driver.clock is { -- Delay sampling wait true(finished); do_something_with(data); }; }; extend my_sequence { !trans1 : READ transfer; !trans2 : WRITE transfer;
5-46
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Handling Pipelined Protocols

body()@driver.clock is { var num_of_items : uint; all of { -- Create separate thread for each do-sample pair { // First thread do trans1; num_of_items = 1; trans1.get_data(); }; { sync true(num_of_items==1); do trans2; trans2.get_data(); }; }; }; extend my_bfm { bfm_loop()@clock is { while TRUE { trans = driver.get_next_item(); start put_on_bus(trans); -- Emit the item_done event when the trigger event occurs wait @need_new_item; emit driver.item_done; }; }; }; // Second thread

Example 2

All do actions in a single thread but sampling in separate threads

extend transfer { -- Add Boolean field !finished : bool; get_data()@driver.clock is { -- Delay sampling wait true(finished); do_something_with(data); }; }; extend my_sequence { !trans1 : READ transfer;

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-47

Sequences: Constructing Test Scenarios


Miscellaneous Advanced Features

!trans2 : WRITE transfer; body()@driver.clock is { message(NONE,"running ",kind," burst"); do trans1; start trans1.get_data(); // Sample in separate thread do trans2; start trans2.get_data(); // Sample in separate thread }; }; extend my_bfm { bfm_loop()@clock is { while TRUE { trans = driver.get_next_item(); start put_on_bus(trans); -- Emit the item_done event when the trigger event occurs wait @need_new_item; emit driver.item_done; }; }; };

5.10 Miscellaneous Advanced Features


This section includes:

Disabling Automatic Launch of the MAIN Sequence on page 5-48 Creating a Common Base for Your Sequences and Sequence Drivers on page 5-49 Applying Default Behavior When No Item Is Done on page 5-51 Synchronization within a Cycle on page 5-52 Quitting Sequences and Sequences Items on page 5-54

5.10.1

Disabling Automatic Launch of the MAIN Sequence

Normally, the MAIN sequence is generated and started automatically upon driver.run(). However, you can disable this automatic process. To disable automatic generation and launching of the MAIN sequence:

Constrain the gen_and_start_main eld under the sequence driver to be FALSE.


e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-48

Sequences: Constructing Test Scenarios


Creating a Common Base for Your Sequences and Sequence Drivers

For example:
extend ex_atm_driver { keep soft gen_and_start_main == FALSE; };

5.10.2

Creating a Common Base for Your Sequences and Sequence Drivers

A typical environment contains several sequences that use different items and also virtual sequences. For example:
sequence atm_sequence using item=atm_cell; sequence ethernet_sequence using item=ethernet_packet; sequence comm_sequence;

Although atm_sequence, ethernet_sequence, and comm_sequence are different sequence families, they can have a common logic and functionality. Therefore, you might want to dene a common base for your sequences and a common base for your drivers. Some times when this could be useful are:

When using layered sequence drivers that have a common functionality (for example, in the way
they extract data from the higher-level driver)

When you want each sequence to print a standard header or footer when it is started or ended When you want to associate different sequences or drivers that use different items in one logic family,
(for example, all AHB sequences) This section includes:

Creating a Common Base for Your Sequences on page 5-49 Creating a Common Base for Your Sequence Drivers on page 5-50

5.10.2.1 Creating a Common Base for Your Sequences


To create a common base for your sequences: 1. Dene a base_sequence struct that inherits from any_sequence (directly or indirectly).
struct base_sequence like any_sequence {

2. 3.

Implement the common logic for your sequences in your base_sequence struct. Add the option sequence_type=base_sequence to the sequence statement for each sequence struct that you want to inherit from base_sequence.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-49

Sequences: Constructing Test Scenarios


Creating a Common Base for Your Sequences and Sequence Drivers

For example:
sequence my_seq using item=my_item, sequence_type=base_sequence;

Specifying sequence_type causes newly created sequence structs to inherit from base_sequence rather than any_sequence. Notes

The base_sequence struct can be derived from another base_sequence struct, not only from
any_sequence.

The base_sequence struct only establishes a common logic. You cannot instantiate or generate an
instance of this type.

5.10.2.2 Creating a Common Base for Your Sequence Drivers


To create a common base for your sequence drivers: 1. Dene a base_sequence_driver unit that inherits from any_sequence_driver (directly or indirectly).
struct base_sequence_driver like any_sequence_driver {

2. 3.

Implement the common logic for your sequence drivers in your base_sequence_driver unit. Add the option sequence_driver_type=base_sequence_driver to the sequence statement for each sequence with a sequence driver that inherits from base_sequence_driver. For example:
sequence my_seq using item=my_item, sequence_driver_type=base_sequence_driver;

Specifying sequence_driver_type causes newly created sequence drivers to inherit from base_sequence_driver rather than any_sequence_driver. Notes

The base_sequence_driver unit can be derived from another base_sequence_driver unit, not only
from any_sequence_driver.

The base_sequence_driver only establishes a common logic. You cannot instantiate or generate an
instance of this type.

5-50
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Applying Default Behavior When No Item Is Done

5.10.3

Applying Default Behavior When No Item Is Done

Some designs require the BFM to perform activity under any circumstances. For example, some buses require a continuous transmission of data, even if it is an idle data. For such designs, using the normal hookup scheme cannot sufce; because in those schemes, if there is no valid do action at the moment, the sequences block any BFM activity. In other words, the return of get_next_item() is blocked until a valid do action exists. To solve such cases, you can use the try_next_item() TCM:
any_sequence_driver.try_next_item(): seq_item @clock;

This TCM tries to return the current item being done by the sequences. However, unlike get_next_item(), if no such item exists, it returns NULL in the same cycle that it is called. This lets the user create a default item instead of the item that was supposed to be created by the sequences, thereby adhering to the DUT rules. Note try_next_item() does not just look for an existing candidate for a do but also allows sequences to execute their body() TCMs and then look for a possible do action. This is done by calling the wait_for_sequences() TCM (see Solving Possible Race Conditions on page 5-53). To apply default behavior when no item is currently created by the sequences: 1. Replace the call to driver.get_next_item() (as demonstrated in Step 4 of the hookup scheme in Hooking the Sequence Driver to the Environment on page 5-9) with a call to the try_next_item() TCM. Note This method must be used in PULL_MODE only. 2. When try_next_item() returns NULL, explicitly create your item instead.

Example
extend ex_atm_bfm { pull_send_loop() @clock is only { var seq_item: ex_atm_cell; while TRUE { seq_item = driver.try_next_item(); if seq_item == NULL { seq_item = new; }; drive_cell(seq_item); emit driver.item_done; }; }; };

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-51

Sequences: Constructing Test Scenarios


Synchronization within a Cycle

See Also Figure 5-20 on page 5-124 Figure 5-19 on page 5-123

5.10.4

Synchronization within a Cycle

This section contains:

Delaying the Driver Clock on page 5-52 Solving Possible Race Conditions on page 5-53 Forcing a Reevaluation of the do Action Queue on page 5-54

5.10.4.1 Delaying the Driver Clock


Sometimes you must let the environment execute before the sequences execute. A typical example is when a BFM must export its status before sequences are evaluated so that they can use the new status to generate updated data. To enable an intracycle delay (a delay within the same cycle) of sequence activity:

Use the delay_clock() TCM.


any_sequence_driver.delay_clock() @sys.any;

After an intracycle delay, the delay_clock() TCM emits the drivers clock just once. To delay the driver clock: 1. 2. Remove any connection to the driver clock (see the hookup scheme in Hooking the Sequence Driver
to the Environment on page 5-9).

Dene a TCM that calls to driver.delay_clock() every cycle. For example:


extend ex_atm_bfm { delay_driver_clock() @a_clock is { while TRUE { // Emit the driver.clock after some delay driver.delay_clock(); wait cycle; }; }; run() is also {

5-52
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Synchronization within a Cycle

start delay_driver_clock(); }; };

Note This TCM replaces the regular clock connection, so make sure that the clock is not also emitted.

5.10.4.2 Solving Possible Race Conditions


In complicated environments (for example multilayer environments), a race condition might occur between parallel threads of TCMs. For example, this could occur between layered BFMs or between the BFM and the sequence driver. A typical case is when one thread produces some data that another thread consumes. If the consumer is evaluated before the producer, it could happen that the consumer will be called rst and will miss the producer, even though both occurred in the same cycle. Solving such cases can be done by explicitly performing a context switch in the consumer that lets the producer be evaluated rst. To perform a context switch that forces a producer to be evaluated before a consumer:

Use the wait_for_sequences() TCM:


For example:
any_sequence_driver.wait_for_sequences() @sys.any;

This TCM can be called by the consumer before or in parallel with waiting for the producer. This TCM does not exceed the boundary of the cycle but uses time-consuming actions such as sync [0] to create an articial context switch. This TCM is already used in the sequence mechanism in the call to try_next_item(). try_next_item() calls wait_for_sequences() to allow evaluation of the sequences before looking for existing do actions. You can also extend or override this TCM if the existing implementation does not satisfy the needs of your environment. For example:
extend ex_atm_driver { wait_for_sequences() @sys.any is only { for i from 1 to 100 { sync [0]; }; }; };

Note Overriding wait_for_sequences() also affects the behavior of try_next_item().

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-53

Sequences: Constructing Test Scenarios


Quitting Sequences and Sequences Items

5.10.4.3 Forcing a Reevaluation of the do Action Queue


When there is a demand for items, the driver chooses a do action only if the is_relevant() method of the sequence returns TRUE. But the returned value of is_relevant() might depend on the current state of the environment. In that case, the driver might fail to choose a do action when the sampling time of is_relevant() is prior to the changes in the env. In that case, you can force a reevaluation of the do action queue. To force a reevaluation of the do action queue:

Call the method driver.check_is_relevant().


Note This check_is_relevant() method is meaningful only for synchronization within a cycle. When a new cycle starts, the driver automatically reevaluates the queue.

5.10.5

Quitting Sequences and Sequences Items

Specman Elite continues evaluating temporal expressions until quit() is called. Garbage collection for a struct only occurs after Specman Elite stops evaluating the structs temporal expressions. This also applies for sequences and sequence items. Therefore, if you use temporal expressions in a sequence or sequence item, quit() must be called before Specman Elite can perform garbage collection on the sequence or sequence item. To enable automatic quitting of sequences and sequence items:

Set the predened method any_sequence_item.auto_quit() to TRUE.


extend any_sequence_item { auto_quit() : bool is only { return TRUE; }; };

When auto_quit() returns TRUE, quit() is automatically called for sequences after the sequence is nished and for sequence items after driver.item_done is emitted. Note By default, auto_quit() currently returns FALSE. In future, the default will change to TRUE. You can override the setting of auto_quit() for specic types. To override the auto_quit() setting:

Extend the relevant sequence or sequence item type.


For example:
extend my_sequence_item { auto_quit() : bool is only {
5-54
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Layering of Protocols

return FALSE; }; };

5.11 Layering of Protocols


This section discusses the layering of protocols and how to implement it using sequences. This section includes:

Introduction to Layering on page 5-55 Styles of Layering on page 5-59 Using Layered Sequence Drivers on page 5-63

5.11.1

Introduction to Layering

Simple eVCs and VEs might not need layering of protocols, but in complex situations it is often required. Two examples are TCP/IP over Ethernet and ATM over Sonet. Sequence layering and virtual sequences are the two main ways in which sequence drivers can be composed to create a bigger whole. In the erm_lib directory, there are two example packages that demonstrate layering: ex_blayers This eRM package (basic layers) demonstrates a simple layering conguration. It shows a low-layer packet sequence driver that can either work alone or pull information from a high-layer frame sequence driver. (For details, see the PACKAGE_README.txt of the package.) This eRM package demonstrates the use of multiple high- and low-layer sequence drivers as well as virtual sequence drivers, all interacting in the layering scheme. It also demonstrates late binding of the various layers (emulating a situation where different people wrote separate eVCs that are later bound together by yet another person). (For details, see the PACKAGE_README.txt of the package.)

ex_layers

This section includes:

What Is Layering of Protocols? on page 5-56 Layering and Sequences on page 5-56

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-55

Sequences: Constructing Test Scenarios


Introduction to Layering

5.11.1.1 What Is Layering of Protocols?


The classic example is where the don't-care data (just a list of byte) in the lower-level protocol suddenly is forced by the higher-level protocol to be meaningful. For example, assume that there are two sequence drivers. The low-layer sequence driver drives packets that are dened as:
struct packet like any_sequence_item { data[10]: list of byte; ... -- Other fields };

So the low-level sequence driver is dened as:


sequence packet_sequence using item = packet;

In one case, you just want to send packets with random data. In another case, you want the data to come from a higher-layer data protocol. The higher-layer protocol in the example drives frames. So the high-level sequence driver is dened as:
sequence frame_sequence using item = frame;

A frame would then have various elds that must be packed together and sent in the data lists of n consecutive packets.

5.11.1.2 Layering and Sequences


Layering is best implemented in e via sequences. There are two main ways to do layering using sequences:

Layering Inside One Sequence DriverApplies for simple cases only Layering of Several Sequence DriversApplies for all layering needs Layering Inside One Sequence Driver
In this case, you simply generate a data item of the higher layer within the lower-layer sequence. You do that by inventing another sequence kind for the lower-layer sequence driver. For example:
extend packet_sequence_kind: [FRAME_SENDER];

The FRAME_SENDER sequence generates a single frame and sends it in chunks, in one or more packets, until the data of the frame is exhausted. For example:
extend FRAME_SENDER packet_sequence { frame: frame; !packet: packet;
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-56

Sequences: Constructing Test Scenarios


Introduction to Layering

body() @driver.clock is { var full_data: list of byte = pack_the_frame(); // Pack the frame while not done_with_full_data() { // while not done with full_data var next_piece: list of byte=get_next_chunk_from_full_data(); do packet keeping {.data == next_piece}; }; }; };

The FRAME_SENDER sequence can then be used by other sequences. For example, you could dene a SUPER_FRAME_SENDER packet_sequence that takes a super_frame (whatever that is), chops it into frames, and executes in a loop as follows:
do FRAME_SENDER sequence keeping { .frame == get_next_frame_in_super_frame(); };

Layering inside one sequence driver is easy to write and understand. However, it only works well in simple cases. For complex cases, you need a more general approach.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-57

Sequences: Constructing Test Scenarios


Introduction to Layering

Layering of Several Sequence Drivers


Figure 5-4 Layering Architecture
DUT Packet BFM This packet sequence pulls information directly from the Frame sequence driver

seq seq

Packet SD

seq

Multi-Layer Architecture

seq seq

Frame SD

seq

DUT Packet BFM Single-Layer Architecture

seq

seq seq

Packet SD

The more general approach uses multiple sequence drivers (see Figure 5-4 on page 5-58). Taking the frame and packet example, there would be a low-layer packet_sequence and a high-layer frame_sequence (complete with their sequence drivers). The packet_sequence would pull data from the frame_sequence_driver (or from its BFM). Each sequence driver might even be encapsulated in an eVC so that layering could be done by connecting the eVCs.

See Also Using Layered Sequence Drivers on page 5-63

5-58
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Styles of Layering

5.11.2

Styles of Layering

This section includes:

Applies for all layering needs One-to-One, One-to-Many, Many-to-One, Many-to-Many on page 5-60 Different Congurations at Pre-Run Generation and Runtime on page 5-61 Timing Control on page 5-61 Data Control on page 5-62 Complex Inter-Packet Dependencies on page 5-62 Using Virtual Sequence Drivers on page 5-62

5.11.2.1 Basic Layering


The simplest general scenario is:

The actual BFM accepts layer1 packets. The layer1 packets are constructed out of layer2 packets in some way, the layer2 packets are in turn
constructed out of layer3 packets, and so on.

Between every layerN and layerN+1, there is a mechanism that takes layerN+1 packets and converts
them into layerN packets. You could also have multiple kinds of layer1 and layer2 packets (as in Figure 5-5 on page 5-60). In different congurations you might want to layer any kind of layer2 packet over any kind of layer1 packet. The rest of this section describes some possible variations and complications, depending on the particular protocol or on the desired test-writing exibility.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-59

Sequences: Constructing Test Scenarios


Styles of Layering

Figure 5-5 Layering of Protocols


Kinds: RAW LAYER2A LAYER2B Layer 1a Layer 1b Layer 2a Layer 2b
header kind Payload (32 heade kind Payload (32 bytes) bytes) header address 1 byte address 1 byte length 1 byte Payload (1..100 bytes) kind Payload (64 bytes) Payload (31 bytes) CRC CRC CRC

5.11.2.2 One-to-One, One-to-Many, Many-to-One, Many-to-Many


Figure 5-6 Layer Mapping
One to One Layer 2a 2A Layer 1a
header kind Payload (32 bytes) CRC address Payload (31 bytes)

Many to One Layer 2a 2A Layer 1b


header kind Payload (64 bytes) CRC address Payload (31 bytes)

Many to Many
add len Payload (20 bytes) add len Payload (20 bytes) add len Payload (18 bytes)

2B
header kind Payload (32 bytes) Payload (32 bytes) hea kind CRC CRC header kind Payload (32 bytes) CRC

5-60
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Styles of Layering

The conversion mechanism might need to cope with any of the following situations: One-to-one One-to-many Many-to-one Many-to-many One high-layer packet must be converted into one low-layer packet. One big high-layer packet must be broken into many low-layer packets. Many high-layer packets must be combined into one big low-layer packet (as in Sonet). Multiple higher-layer packets must be taken in and converted into multiple lower-layer packets. For example, high-layer packets are 10 bytes long, and low-layer packets are 3 to 35 bytes long. In this case, there could be remainders.

5.11.2.3 Different Configurations at Pre-Run Generation and Runtime


You might want to build different congurationseither by loading different les or by randomizing something during pre-run generation. For example, in one conguration, you might have only layer1 packets. In another conguration, layer1 packets would be dictated by layer2 packets. You might also want to decouple the layers further, for example, so that layer2 packets could drive either layer1 packets or layer1 cells (at another interface) or both. The general picture here is boxes with connecting pipes. At pre-run generation, you can connect the pipes according to the required conguration or topology. Sometimes, you might want to decide on the mix of input from multiple sources at runtime. For example, you might want to have one low-layer sequence driver send n packets that come from one high-layer sequence driver and then m packets from another high-layer sequence driver.

5.11.2.4 Timing Control


In some congurations, the high-layer packets drive the timing completely. When high-layer packets are created, they are immediately converted into low-layer packets. In other congurations, the low-layer sequences pace the operation. When a low-layer do is executed, the corresponding high-layer packet should appear in zero time, much like with reactive sequences. Finally, there is a case where things are driven into the DUT according to the timing of the low-layer sequences, but the high-layer sequences are not reacting in zero time. Rather, if there is no data available from the high-layer sequences, then some default value (for example, a zero ller) is used instead.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-61

Sequences: Constructing Test Scenarios


Styles of Layering

5.11.2.5 Data Control


In some congurations, the high-layer transactions completely dictate what low-layer items reach the DUT. The low layer simply acts as a slave. Often, however, both layers inuence what reaches the DUT. For example, the high layer might inuence the data in the payload while the low layer inuences other attributes of the items reaching the DUT. As such, the choice of sequences for both layers is meaningful.

5.11.2.6 Complex Inter-Packet Dependencies


In some cases, complex transformations must be performed. Just shoving data from the high layer to the low layer will not sufce. For example: Serial number handling Assume that each packet has serial numbers, and serial numbers should be given using some global algorithm that takes into account all high-layer requests. Assume that this is a two-way protocol. The other side can send back ACK and NACK (acknowledge and not acknowledge) packets, and the high-layer protocol must retransmit some packets accordingly. At the same time, you might already be outside the high-layer request that created the original packet for which a NACK was received.

Retransmit handling

Complex blocking issues Assume that a given low-layer sequence driver is sending packets from one high-layer source that drives a high-layer transaction to one target (slave). Assume also that the target cannot receive packets for other high-layer transactions; however, other targets can. Thus, the given low-layer sequence driver can process multiple high-layer transactions at the same time, as long as you do the necessary queueing so that any subsequent high-layer transactions to the same slave wait for their turn in the correct queue. One thing common to all of these examples is the need for some global information (the counter in the rst example and the queue in the last example) and some corresponding global control.

5.11.2.7 Using Virtual Sequence Drivers


In the most general case, you have a graph consisting of several virtual sequence drivers and several BFM sequence drivers. Some low-layer BFM sequence drivers are connected to the DUT, some higher-layer BFM sequence drivers are layered above them, and some virtual sequence drivers on top feed into all of the BFM sequence drivers below.

5-62
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Using Layered Sequence Drivers

In the example conguration shown in Figure 5-7 on page 5-63, a low-layer sequence driver (L1B) gets input from multiple high-layer sequence drivers (two instances of L2A) as well as from a virtual sequence driver. Figure 5-7 Most General CaseUsing Virtual Sequence Drivers
Layering with virtual sequences Layering with connector sequences Virtual SD seq seq seq

L2B SD seq L2A SD seq seq seq

seq seq L2A SD seq seq seq L2A SD seq seq seq

L2B BFM
seq seq

L1A
seq

L1B SD
seq

seq seq

L1A BFM DUT

L1B BFM

5.11.3

Using Layered Sequence Drivers

The general solution for layering involves multiple, layered sequence drivers. Assume that at the low layer you have a packet_sequence (and a packet_sequence_driver), and above it you have a frame_sequence (and a frame_sequence_driver). Packets can either be layered (that is, their payload contains data from frames) or independent (that is, their payload is random). (See Figure 5-4 on page 5-58.) This section includes:

Overview of the Layering Solution on page 5-64 Introducing Layering into the Low-Layer Sequence on page 5-65 Late Binding on page 5-67

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-63

Sequences: Constructing Test Scenarios


Using Layered Sequence Drivers

5.11.3.1 Overview of the Layering Solution


Layered sequence drivers work as follows:

Lowest-layer sequence drivers send information to a real BFM (which typically toggles actual DUT
signals).

Higher-layer sequence drivers only send information to lower-layer sequence drivers. They may or
may not have their own BFMs, depending on whether complex transformations are needed from the higher layer to the lower layer.

Lower-layer drivers point to the higher-layer driver(s) from which information must be pulled (using
get_next_item() / try_next_item() or some connector method). The actual pointer conguration is normally decided during pre-run generation. The pulled information (either the higher-layer data or some transformation thereof) is put in a eld of the sequence and is then used to constrain various elds in the lower-layer item(s). Following is an example of a connector packet sequence that pulls a single frame from the frame sequence driver and then sends it as packets:
extend FRAME_SENDER packet_sequence { !frame: frame; !packet: packet; body() @driver.clock is { -- Get the frame from the frame_driver frame = frame_driver.get_next_item(); emit frame_driver.item_done; var full_data: list of byte = pack_the_frame(); while not done_with_full_data() { var next_piece: list of byte = get_next_chunk_from_full_data(); do packet keeping {.data == next_piece}; }; }; };

Note This simple example is very similar to the one in Layering and Sequences on page 5-56. But there the frame was generated in the packet_sequence, and here it is pulled from the frame sequence driver. There are several ways to get information from a higher layer:

You can get information from the higher layer by calling frame_driver.get_next_item() directly and
getting a frame (as was done in the single-item connector example above):
frame = frame_driver.get_next_item();
5-64
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Using Layered Sequence Drivers

You can call a method of the higher-layer BFM, not a method of the higher-layer sequence driver.
For example, you might want the BFM to do some transformations on the higher-layer data, returning a list of bytes somehow extracted from it. For example:
raw_data = frame_bfm.get_data();

Note The BFM is called here in PULL_MODE. It would probably use get_next_item() to get the data from the higher-layer sequence driver, also in PULL_MODE. (See Figure 5-8 on page 5-65.)

You can call some intermediate connector method in the lower-layer sequence driver, which will
later be extended (see Late Binding on page 5-67). For example:
raw_data = driver.get_payload();

Figure 5-8 Pulling Information from a High-Level BFM


Frame SD
seq

seq seq

Frame BFM

To achieve complex data transformation, we need a BFM or a third-party transformer unit.

Packet SD
seq

seq seq

This sequence pulls from the Frame BFM.

Packet BFM DUT

5.11.3.2 Introducing Layering into the Low-Layer Sequence


This section explains the three main ways to introduce layering into the low-layer sequence so that it will be able to pull information from above and use it:

Using a Single-Item Connector Sequence Using Implicit Connection (by Extending the Low-Layer Sequence) Using a Protocol-Aware Multi-Item Connector Sequence
Your needs will determine which way is best for you.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-65

Sequences: Constructing Test Scenarios


Using Layered Sequence Drivers

Using a Single-Item Connector Sequence


Sometimes, you want to freely mix layered packets (packets whose payload comes from frames) with independent packets. To allow for single-item granularity, you can use a single-item connector sequence, as demonstrated in Overview of the Layering Solution on page 5-64. The sequence takes a single high-layer item (frame in the example) and produces one or more low-layer items (packets in the example).

Using Implicit Connection (by Extending the Low-Layer Sequence)


Another situation is where you initially have a whole library of lower-layer sequences. Suddenly, you want all lower-layer data items in all sequences to be layered. To do that, you can extend the basic, low-layer sequence (rather than a specic CONNECTOR sequence) and pull the information from above using the pre_do() method. This lets you avoid changing the original body() method (which was customized for each sequence in the library). Following is an example of implicit connection by extending a low-layer sequence:
extend packet_sequence { use_layering: bool; keep soft use_layering == FALSE; keep in_seqence(packet_sequence) (p) => soft use_layering == p.use_layering; !raw_data: list of byte; pre_do(is_item: bool) @sys.any is { if is_item and use_layering then { raw_data = frame_bfm.get_data(); -- Here you get the information from the frame BFM, not from the -- frame sequence driver just to demonstrate this possibility. }; }; }; extend packet { keep in_sequence(packet_sequence) (p) and p.use_layering => data == p.raw_data; };

Loading the above code and constraining use_layering to TRUE makes that sequence (and sequences underneath it) use layering:
extend MAIN packet_sequence { keep use_layering == TRUE; };

5-66
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Using Layered Sequence Drivers

Note This allows conditional layering. If that is not needed, you can remove the use_layering ag and the logic around it.

Using a Protocol-Aware Multi-Item Connector Sequence


Finally, there are cases where, in layered mode, the full low-layer sequence is (almost) completely determined by the protocol. Quite often, there is no way to mix layered and independent data items without breaking the protocol and causing the DUT to go into an error state. For example, the protocol might involve complex retransmit and blocking rules (see Complex Inter-Packet Dependencies on page 5-62). The logic for these rules could either be embedded in the BFM of the high-layer sequence driver (in which case the low-layer sequence is relatively free from restrictions) or embedded in the low-layer sequence (in which case it becomes protocol-aware and has very little freedom). A protocol-aware sequence is typically a multiple data-item sequence (quite often lasting throughout the test). Generally, it pulls the full high-layer item (frame in the example) as is from the layer above, adding it to some global list (in the sequence itself or in the sequence driver). It then starts to create low-level data items as needed. As required (for example, upon a NACK), it would consult the global list and other global elds and do the appropriate thing (for example, retransmit some packets). While this sounds like one, monolithic sequence, it might still have some degree of freedom (perhaps freedom in timing or various ways to respond to a NACK). These should be encoded as generatable elds in the sequence (and its subsequences), which could be constrained from outside.

5.11.3.3 Late Binding


Sometimes several people (or groups of people) can be involved in the development of layers. There are several possibilities regarding how many persons are involved in the development and the role that each person plays. In addition, there is the test writer, who uses constraints to dene the actual conguration of sequence drivers (and many other things).

One Person
Sometimes, the same party two layers and the connection between them are written together. This typically occurs when the two layers always go together.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-67

Sequences: Constructing Test Scenarios


Using Layered Sequence Drivers

Two Persons
In some cases, the lower layer was written by a person with no knowledge of layering. Thereafter, the higher layer is written by another person specically for that lower layer. In this case (as in the previous one), this strong coupling makes it possible to customize the BFM of the higher layer as needed to match the low layer. This is demonstrated in the ex_blayers example package.

Three Persons
In this case:

Person A writes the lower-layer part (item, sequence, sequence driver, BFM). Person B writes the higher-layer part (item, sequence, sequence driver).
A and B do not know about each other and might even ignore the need for layering.

Person C connects the two by writing the connector sequence(s) and the rest of the connecting code. Four Persons
This more general case is the one implemented in the ex_layers package. It goes as follows:

Persons A and B are as in the three-persons case. Person C denes some empty connector methods in the lower-layer driver and then writes the
connector sequences that call those methods to pull in the information.

Finally, person D denes how to pull information from any particular higher-layer source by
extending the connector methods in the lower-layer driver. This more exible scheme allows for the case where each lower-layer sequence driver has multiple connector-unit references that are only wired at conguration time. Thus, a particular sequence (written by person C or by the test writer) could take raw data from one connector unit and then some more data from a second connector unit without caring whether the two connector units are of the same type or not. Example 1. Dene a generic list of connector units and the empty connector methods (get_payload(), get_kind()), which initially just issue an error. Note At this point this is not associated with any specic higher layer.
extend ex_layer1a_driver_u { connectors : list of any_unit;
5-68
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Using Layered Sequence Drivers

keep soft connectors.size() == 0; get_payload(connector : any_unit) : list of byte @sys.any is { error("Unrecognized/NULL connector unit in get_payload()"); }; -- get_payload() }; -- extend ex_layer1a_driver_u

2.

Dene a sequence kind that pulls in a payload and a kind from a (yet unspecied) higher-level sequence driver (or BFM) and stuffs it into a packet.
extend CONNECTOR ex_layer1a_sequence { connector: any_unit; keep connector in driver.connectors; // Defined in Part 1 -- This is raw data coming from the higher layer protocol. !raw_data : list of byte; -- This is the Layer1a kind field coming from the higher-level -- protocol. !packet_kind : ex_layer1a_packet_kind_t; -- Before do-ing items, grab the required data from the -- higher-layer protocol by calling empty connector methods -- defined in the driver (defined in Part 1). pre_do(is_item : bool) @sys.any is also { if is_item { raw_data = driver.get_payload(connector); packet_kind = driver.get_kind(connector); }; }; // pre_do() body() @driver.clock is only { do packet keeping { it.kind == packet_kind; it.payload == raw_data; }; }; // body() }; // extend CONNECTOR ex_layer1a_sequence

3.

In a separate le, specify how to connect layer1a to a specic higher-level driver (layer2a), by extending get_payload().
extend ex_layer1a_driver_u { get_payload(connector : any_unit) : list of byte @sys.any is first { if connector is a ex_layer2a_driver_u (p) { var packet := p.try_next_item(); if packet != NULL { // Has a real packet emit p.item_done;

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-69

Sequences: Constructing Test Scenarios


Tracing and Debugging Sequences

return pack(packing.low, packet); } else { // No real packet. Therefore, return a filler result.resize(32); return result; }; }; }; -- get_payload() };

5.12 Tracing and Debugging Sequences


Table 5-4 describes the tools required for debugging sequences.

Table 5-4 Sequence Debugging Tools Tool Source debugger Thread browser Data browser Waveform viewer Sequence visualization windows Lets you Follow the sequence execution Search for the sequence thread and display its execution tree View the sequence data View the sequence items sent by a driver View detailed information on a sequence and sequence driver, including statistics and history

In addition, you can collect sequence debugging information, to get additional information in the visualization windows (history and current state), tracing messages, and more. This section contains:

Tracing Sequences on page 5-71 Available Debug Information on page 5-74 Using the Sequence Browser on page 5-80 Transaction Attributes on page 5-90 Working in ASCII Mode on page 5-92 show sequence on page 5-94

5-70
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Tracing Sequences

5.12.1

Tracing Sequences

The trace sequence command enables sequence tracing and debugging information on several levels. You must issue this command to access some history data. The trace sequence command also lets you show the tracing mode of each sequence driver (see Showing Trace Information on page 5-72.

Syntax
tra[ce] seq[uence] [destination] [mode] [wild]

Parameters
destination Can be: msg[_only]Specman Elite collects and displays trace information. log[_only]Specman Elite collects and displays trace information as stripes in a VT visualization window. trans[action[s]]Specman Elite records trace information as transactions to be viewed in the SimVision for Cadence NC simulators. Note Currently, the transactions option is not supported on the HP and AIX platforms. allSpecman Elite does all of the above. The default option is all. mode Can be: onTracing is enabled. offTracing is disabled. The default option is on for all drivers. wild Filters the effect of the command to the specied sequence drivers (those with the e path that matches wild).

Description
This command can be activated at any time during the run. It changes the tracing mode for all specied drivers.
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-71

Sequences: Constructing Test Scenarios


Tracing Sequences

5.12.1.1 Showing Trace Information


Syntax
tra[ce] seq[uence] -show

Description
This command shows the tracing mode of each sequence driver.

5.12.1.2 Using the Simulator Waveform


Viewing Sequences as Waveform Transactions
Figure 5-9 Driver Selected for Viewing

5-72
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Tracing Sequences

Figure 5-10 Viewing Sequences as Transactions in Waveform

To view sequences as waveform transactions: 1. In the simulator, open a Design Browser window. A Testbench node appears in the Scopes pane. 2. Expand the Tesbench tree until you reveal the driver leaves. Then select the driver (or drivers) whose sequences you want to view (Figure 5-9). In the right-hand pane, there is an entry for every root sequence of the selected driver(s). In addition, the sequence item for each selected driver is displayed. 3. Send the information to the waveform (for example, by dragging it into the waveform window). Fibers for the root sequences and sequence items appear in the simulator waveform (Figure 5-10) as follows:

Each root sequence is displayed in a separate ber that can be expanded to show any child
sequences. You can see for each transaction the sequence attributes, such as depth and driver e path.
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-73

Sequences: Constructing Test Scenarios


Available Debug Information

If the root sequence is virtual, its child sequences rst appear under the virtual driver and
subsequently appear under a BFM driver. There is a predecessor-successor relationship between the parent virtual sequence and the child BFM sequence.

Each BFM sequence driver has a single sequence item ber. You can see all generated items for
all sequences of the BFM driver. There is a predecessor-successor relationship between every item transaction and the transaction of the items parent sequence.

5.12.2

Available Debug Information

This section describes the available debug information. It contains:

Tracing Lists on page 5-74 Debug Messages on page 5-75 Wave Info on page 5-76 Stripe Info on page 5-77 State Info on page 5-77

5.12.2.1 Tracing Lists


During the run, trace lists are collected when the trace level is log_only or on. The trace list of a sequence driver contains all sequences and items scheduled by the driver. The list can be retrieved by the following predened methods of any_sequence_driver:

get_trace_list() : list of any_sequence_item get_item_trace_list() : list of any_sequence_item get_sequence_trace_list() : list of any_sequence


The trace list of a sequence contains all items and sequences done by the sequence. The list can be retrieved by the following predened method of any_sequence:

get_trace_list() : list of any_sequence_item


To view the trace lists:

Use either of the following commands:


show seq -trace_list show seq -trace_list driver-idx Shows a summary of all sequence drivers in the env Shows the trace list of driver specied by driver-idx

5-74
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Available Debug Information

Note Trace lists are used when showing the stripe chart of the sequence and sequence driver.

5.12.2.2 Debug Messages


During the run, debug messages are printed to the screen when the trace level is msg_only or on. The debug messages specify information about sequence activity. The messages use the TRACE_SEQUENCE tag. The default format of the output is as follows: [time] short-name: SEQ(depth) message-body
Table 5-5 shows the various types of messages and their verbosity.

Table 5-5 Debug Message Format and Verbosity Message Start of sequence (using start()) End of sequence (started using start()) Creation of sequence or item (using the do action) Format of Message Starting sequence-name sequence-name ended sequence-name|item-name created Verbosity LOW LOW For sequences: MEDIUM For items: HIGH Finish do-ing sequence or item sequence-name|item-name done For sequences: MEDIUM For items: HIGH Sending of data item by driver Sequence grabs driver Sequence ungrabs driver Execution of default body() of the MAIN sequence Rerunning a driver Stopping a sequence (using stop()) item-name sent by driver driver-idx sequence-name grabbed/immediately grabbed driver driver-idx sequence-name ungrabbed driver driver-idx MAIN sequence-name: Executing default body() method: doing count sequences Rerunning driver driver-idx sequence-name stopped. All sequences initiated by root-sequence are stopped HIGH MEDIUM MEDIUM LOW LOW MEDIUM

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-75

Sequences: Constructing Test Scenarios


Available Debug Information

Table 5-5 Debug Message Format and Verbosity (continued) Message Quitting a sequence (using quit()) Format of Message sequence-name quit Verbosity MEDIUM

The nice_string() method is used for printing sequences and items in these messages. There is also a method, any_sequence.post_trace(), which gets called for each sequence just after a trace message about it gets printed. This is useful for breakpoints. Following is a sample message output:
Starting the test ... Opening file for debug: atm.elog Running the test ... [0] ATM 1: SEQ(0) Starting MAIN ex_atm_sequence-@2 [0] ATM 1: SEQ(1) PARALLEL_3 ex_atm_sequence-@3 created [0] ATM 1: SEQ(2) SHORT_LONG ex_atm_sequence-@4 created [0] ATM 1: SEQ(2) SHORT_LONG ex_atm_sequence-@5 created [0] ATM 1: SEQ(2) SHORT_LONG ex_atm_sequence-@6 created [0] ATM 1: SEQ(3) ex_atm_cell-@7 (A1 GREEN 2) created [3] ATM 1: SEQ(3) ex_atm_cell-@7 (A1 GREEN 2) sent by drvr 0 [3] ATM 1: SEQ(3) ex_atm_cell-@8 (A1 BLUE 2) created [6] ATM 1: SEQ(3) ex_atm_cell-@8 (A1 BLUE 2) sent by drvr 0 [6] ATM 1: SEQ(3) ex_atm_cell-@9 (A1 GREEN 1) created [8] ATM 1: SEQ(3) ex_atm_cell-@9 (A1 GREEN 1) sent by drvr 0 [8] ATM 1: SEQ(3) ex_atm_cell-@10 (A3 RED 1) created [10] ATM 1: SEQ(3) ex_atm_cell-@10 (A3 RED 1) sent by drvr 0 [10] ATM 1: SEQ(3) ex_atm_cell-@11 (A4 GREEN 5) created [16] ATM 1: SEQ(3) ex_atm_cell-@11 (A4 GREEN 5) sent by drvr 0 [16] ATM 1: SEQ(2) SHORT_LONG ex_atm_sequence-@5 done Last specman tick - stop_run() was called Normal stop - stop_run() is completed Checking the test ... Checking is complete - 0 DUT errors, 0 DUT warnings.

5.12.2.3 Wave Info


This feature is for runtime tracing of items sent by the sequence driver in the waveform viewer.

Syntax
wave seq[uence] [bfm-driver-num]

5-76
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Available Debug Information

Description
This command adds the specied BFM sequence driver (default: all of them) to the waveform viewer. The bfm-driver-num is according to the numbering of the show sequence command. For each sequence driver, the following six lines are added to the waveform: struct item do_line do_location sequence parent_sequence Shows the e path of the sequence driver (constant). Shows the nice_string() of the current item being sent by the sequence driver. Reverts to XXX when no item is being sent. Actual source line of the do that produced this item, with comments. Location of that do, for example, at line 44 in @foo. The nice_string() of the sequence containing the do. The nice_string() of the parent sequence.

5.12.2.4 Stripe Info


This feature is for visualization of sequences using the VT window as part of the visualization of the env. It is available when the tracing level is log_only or on.

5.12.2.5 State Info


The state info contains information about the current state of a sequence, sequence driver, and do action. It lets you see the exact point in the execution of a do action and the interaction between the sequences and the driver. From this information, you can answer questions like:

What happened to this do action? From the state info you can see when a do action is waiting for
scheduling in the drivers queue. You can also see when a do action is in pre_do() waiting for some data from a higher layer and so on.

What happened with this sequence? From the state info you can see that the sequence was mistakenly
stopped, ended normally, and so on. The state info is available when the tracing level is on. The state info is shown in the visualization windows of the sequence and sequence driver or when printing the sequence while working in ASCII mode.
Table 5-6 shows the possible states of a sequence.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-77

Sequences: Constructing Test Scenarios


Available Debug Information

Table 5-6 Sequence States State In pre_body() In body() In post_body() Stopped Ended Unknown Notes Description The sequence is in the middle of pre_body(). The sequence is in the middle of body(). The sequence is in the middle of post_body(). The sequence is stopped. It happened when calling to stop() for this sequence or one of the sequences in the whole sequence tree. The sequence was ended or done normally. The state of the sequence is unknown (see notes below).

The states in pre_body() and in post_body() are relevant only when the sequence was started
using the start() method.

The state is unknown when there was no change in the state after the tracing level was set to on.
It will not happen if you set the tracing level to on before the simulation starts.
Table 5-7 shows the possible states of a do action.

Table 5-7 do Action States State Wait for scheduling In pre_do() Now generated In mid_do() Item in BFM Sequence in body In post_do() Done Skipped Description The do action is waiting for scheduling in the drivers queue. Now executing the pre_do() of the sequence. The item or sequence is now generated. Now executing the mid_do() of the sequence. Item is now in BFM. Now executing the body() of the done sequence. Now executing the post_do() of the sequence. The do action nished normally. The do action was skipped due to stop()/rerun().

5-78
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Available Debug Information

Table 5-7 do Action States (continued) State Unknown Notes Description The state of the do action is unknown (see notes below).

The states wait for scheduling and item in BFM are relevant for do item only. The state sequence in body is relevant for do sequence only. The state is unknown when there was no change in the state after the tracing level was set to on.
It will not happen if you set the tracing level to on before the simulation starts.
Table 5-8 shows the possible states of a BFM sequence driver.

Table 5-8 BFM Sequence Driver States State Idle Trying to choose do Processing do Item in BFM Unknown Notes Description The driver is idle. There is no current call to get_next_item() or try_next_item(), and no do action is currently performed. The driver is trying to choose the do action to perform. A do action was chosen. The driver currently performs it. An item was generated and is now sent to BFM. The driver is waiting for item_done to complete the do action. The state of the driver is unknown (see notes below).

The state is idle from the time item_done is emitted until the next call to
get_next_item()/try_next_item().

The state is item in BFM from the time get_next_item()/try_next_item() returns until item_done
is emitted.

The state is unknown when there was no change in the state after the tracing level was set to on.
It will not happen if you set the tracing level to on before the simulation starts.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-79

Sequences: Constructing Test Scenarios


Using the Sequence Browser

5.12.3

Using the Sequence Browser

The Sequence Browser lets you view all information available for your sequences. The Sequence Browser consists of the following windows: Env Sequences window The main browsing window.

Shows a summary of all sequence drivers in a unit Shows the sequence threads (when there are less than twenty
sequence drivers in the window) Sequence window Sequence Driver window Shows detailed information on the selected sequence Shows detailed information on the selected sequence driver

The content of these windows changes according to the current tracing level of each driver. The window content is updated automatically when something changes during simulation. When the tracing level is none or msg_only, then the windows show basic information. More information is available when the tracing level is log_only and on. This section contains:

Using the Env Sequences Window on page 5-80 Using the Sequence Window on page 5-82 Using the Sequence Driver Window on page 5-84 Finding an Interesting Point to Start on page 5-88 Detecting Problems on page 5-89

5.12.3.1 Using the Env Sequences Window


The Env Sequences window of the Sequence Browser (see Figure 5-11 on page 5-81) lets you view a summary of all sequence drivers in the selected unit. The window contains links to the Sequence Driver window of each sequence driver in the env.

5-80
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Using the Sequence Browser

Figure 5-11 Env Sequences Window

Table 5-9 describes the various ways you can open the Env Sequences window.

Table 5-9 Opening the Env Sequences Window Open Option From the Specman> prompt, issue the show seq command From the Specman> prompt, issue show seq top-unit-name On the View menu of the Source Debugger, select Sequence Browser In an Env window of the eRM Utility, click the Sequences button Result Shows all sequence drivers under sys Show all sequence drivers under the unit top-unit-name Shows all sequence drivers under sys Shows all sequence drivers under the env

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-81

Sequences: Constructing Test Scenarios


Using the Sequence Browser

5.12.3.2 Using the Sequence Window


The Sequence window of the Sequence Browser (see Figure 5-12 on page 5-83) displays all available information on a selected sequence with links to other tools like the Data Browser and the Thread Debugger.
Table 5-10 shows the information contained in the Sequence window.

Table 5-10 Sequence Window Information Info Enclosing env Driver Sequence type State Activation mode Parent sequence Items sent Grabbing driver Start/End time Description Link to the env The sequence driver The type of the sequenceBFM or virtual (Available only when the tracing level is on) All possible states of the sequence, when the current state is marked Species whether the sequence was started or done The parent sequence (if any) (Available only when the tracing level is log_only or on) The number of items sent by the sequence and its descendents Species whether the sequence is currently grabbing the driver (Available only when the tracing level was set to log_only or on before the sequence was started) The time the sequence was started or ended. For a started sequence, the start_time is the time the start_sequence() method is called. For a subsequence, the start_time is the time the sequence is generated. History stripe button (Available only when the tracing level is log_only or on) Opens the history stripe chart of the sequence to show all items and sequences done by the sequence. (Available only when the sequence is still active) Opens the active stripe chart of the sequence to show sequences and items currently done by the sequence (Available only when the sequence is still active) Opens the thread debugger to show the sequence thread tree Link to the source of the sequence body() (including all of its extensions)
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

Full Active stripe button Thread Tree button body() source


5-82

Sequences: Constructing Test Scenarios


Using the Sequence Browser

Table 5-10 Sequence Window Information (continued) Info Comments Description Comments on the tracing level

Note The number of items sent by the sequence and the stripe charts of the sequence are based on the trace list of the sequence. This might not be accurate if the tracing level was none or msg_only during part of the sequence run. Figure 5-12 The Sequence Window

Table 5-11 describes the various ways you can open the Sequence window.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-83

Sequences: Constructing Test Scenarios


Using the Sequence Browser

Table 5-11 Opening the Sequence Window Open Option From the Specman> prompt, issue the show seq sequence-name command In the Data Browser, click the Visualize button In the other Sequence Browser windows (Env or Sequence Driver), click a sequence link On the View menu of the Source Debugger, select Sequence when the me is a sequence In the Thread Browser, click the Sequence button when the me of the selected thread is a sequence In the Thread Tree window, click the Sequence button when the me is a sequence Result Shows the specied sequence sequence-name Shows the selected sequence Shows the selected sequence Shows the current sequence Shows the current sequence Shows the current sequence

5.12.3.3 Using the Sequence Driver Window


The Sequence Driver window of the Sequence Browser (see Figure 5-13 on page 5-87) displays all available information on a sequence driver with links to other tools like the Data Browser and the Thread Debugger.
Table 5-12 shows the information contained in the Sequence Driver window.

Table 5-12 Sequence Driver Window Information Info e path Enclosing env Driver type State Grabbing sequence Pending grabbers Description Driver path from sys Link to the env The type of the driver BFM or virtual (Available only when the tracing level is on) All possible states of sequence driver, when the current state of the driver is marked The sequence currently grabbing the driver (if any) List of all sequences waiting to grab the driver (if any) BFM Only No No No Yes No No

5-84
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Using the Sequence Browser

Table 5-12 Sequence Driver Window Information (continued) Info Number of items sent Number of pending do actions Current item Tracing level Description (Available only when the tracing level is log_only or on) The number of items sent by the driver Number of do (item) actions waiting in the driver queue. The item currently being sent Shows the current tracing level of the sequence driver. Also shows other tracing levels. You can change the tracing level by selecting another value. (Available only when the tracing level is log_only or on) Opens a window showing the stripe chart of the driver (Available only when the tracing level is log_only or on) Opens a window showing the thread that last called driver.get_next_item(). Indicates whether the driver is shown in the wave. (To add the driver to the wave, click the Add To Wave button) (Available only when the tracing level is on) Current do action handled by the driver. The following information is shown: BFM Only Yes Yes Yes No

Stripe button Requesting Thread Wave Current do

No Yes Yes

Sequence do-ing it Source of the do action Whether belongs to the grabbing sequence (Not applicable if
no sequence is grabbing the driver)

State of the do action Item generated


List of pending do actions A table specifying all do actions waiting in the driver queue. For each do action, the following information is shown: Yes

Index of the do action Sequence do-ing it Source of the do action Whether belongs to the grabbing sequence (Not applicable if no sequence is grabbing the driver) Current result of the do-ing sequences is_relevant() method

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-85

Sequences: Constructing Test Scenarios


Using the Sequence Browser

Table 5-12 Sequence Driver Window Information (continued) Info List of started sequences Description A table specifying all active sequence threads under the driver. For each sequence, the following information is shown: BFM Only No

Index of sequence Name of sequence Status of the sequence Number of items sent by the sequence Button to show the history stripe of the sequence Button to show the active stripe of the sequence Button to show the sequence thread tree in the Thread Debugger

The last two buttons are available only when the sequence is active. The number of items sent and the stripe chart are available only when the tracing level is log_only or on. The status of the sequence is available only when the tracing level is on. Notes

The BFM Only column species whether the information is shown just for BFM sequence drivers
(Yes) or also for virtual drivers (No). Virtual sequence drivers lack the complex logic of a BFM sequence driver.

For virtual drivers, a list of subdrivers are shown only if get_sub_drivers() is implemented. The Add To Wave button is disabled when a driver is already added to the wave. The list of pending grabbers is shown only when there are sequences waiting for the grab. The number of items sent, the stripe charts of the driver, and the stripe charts of started sequences
are based on the trace list of the driver. They might not be accurate if the tracing level was none or msg_only during part of the run.

5-86
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Using the Sequence Browser

Figure 5-13 The Sequence Driver Window

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-87

Sequences: Constructing Test Scenarios


Using the Sequence Browser

Table 5-13 describes the various ways you can open the Sequence Driver window.

Table 5-13 Opening the Sequence Driver Window Open Option From the Specman> prompt, issue the show seq sequence-driver-name command. In the Data Browser, click the Visualize button In the other Sequence Browser windows (Env or Sequence Driver), click a sequence driver link. On the View menu of the Source Debugger, select Sequences when the me is a sequence driver. In the Thread Browser, click the Sequences button when the me of the selected thread is a sequence driver. In the Thread Debugger, click the Sequences button when the me is a sequence driver. Result Shows the specied sequence driver sequence-driver-name Shows the selected sequence driver Shows the selected sequence driver

Shows the current sequence driver

Shows the current sequence driver

Shows the current sequence driver

5.12.3.4 Finding an Interesting Point to Start


A complex environment might include:

Multiple eVCs Multiple instances of an eVC Multiple threads Multiple visualization windows
To nd an interesting starting point:

Select the interesting unit and display its Env Sequences window. Then in the Env Sequences window,
click a link to the window of an interesting sequence driver. Or

If you know the interesting sequence or sequence driver, open its window directly (using links,
buttons, or the show sequence command).

5-88
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Using the Sequence Browser

Or

If there are many threads, use the Sequence Driver window to nd an interesting sequence thread to
debug with the source debugger.

5.12.3.5 Detecting Problems


The Sequence and Sequence Driver windows can help you detect problems. By examining the information shown in the window, you can understand what is the current state of the sequence and the sequence driver. From the state of the sequence and the sequence driver, you can detect many problems. Table 5-14 Identifying Problems from Sequence and Sequence-Driver States State idle trying to choose do Possible Problem When the driver state remains idle, the driver clock might not be connected or there was no call to get_next_item(). This can be veried by examining the code. When the driver state remains trying to choose do, this can imply one of the following:

No sequence is currently do-ing items. This can be veried by examining the


do actions in the driver queue displayed in the Sequence Driver window.

A sequence is grabbing the driver but not do-ing any items. This can be veried
by examining the grabbing sequence and the do actions in the driver queue displayed in the Sequence Driver window.

The is_relevant() method returns FALSE for all sequences that are trying to
do items. This can be veried by examining the do actions in the driver queue displayed in the Sequence Driver window and sampling their is_relevant() method. Processing do When the driver state remains processing do, the sequence might be hanging while in pre_do(). This can be veried by examining the state of the current do action in the Driver window or by examining the sequence thread in the Source Debugger. When the driver state remains item in BFM, item_done might not have been emitted or the BFM cannot process item_done. This can be veried by locating the thread that calls to get_next_item().

Item in BFM

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-89

Sequences: Constructing Test Scenarios


Transaction Attributes

5.12.4

Transaction Attributes

Specman Elite uses a predened set of attributes when recording transactions. The predened set of attributes varies in accordance with the transaction type: root sequence (depth == 0), regular sequence (depth > 0), or sequence item.
Figure 5-14 shows how the waveform displays these attributes.

Figure 5-14 Transaction Attributes

For version 5.6 or earlier of NC simulators, attribute inheritance takes place. In other words, transactions inherit the attributes of their parents. From version 5.7, there is no attribute inheritance. For example, the driver e-path attribute belongs to the predened set of attributes for root sequence transactions but not for regular transactions. Nevertheless, in Figure 5-14 (which is captured from the 5.6 NC simulator), the waveform displays this attribute for all sequences, root and regular.

5.12.4.1 Adding Attributes to Transactions


Sequences and sequence items in your design have elds that are specic to the design. As these elds are user-dened, they are not represented in the predened sets of transaction attributes.

5-90
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Transaction Attributes

To add custom transaction attributes:

Implement the method get_traced_eld_names() for the relevant type.


The method returns a list of eld name strings.

Example 1

Adding a single transaction attribute

In the vr_xbus eVC, the eld master_name of the master sequences (type: vr_xbus_master_sequence) is specic to the design. As such, Figure 5-14 does not display an attribute for this eld. You could add an attribute for the master_name eld by extending the vr_xbus_master_sequence type as follows:
extend vr_xbus_master_sequence { get_traced_field_names() : list of string is { result.add("master_name"); }; }; Figure 5-15 shows the resultant waveform with the master_name attribute.

Figure 5-15 Custom Transaction Attributes

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-91

Sequences: Constructing Test Scenarios


Working in ASCII Mode

Example 2

Adding multiple transaction attributes

Assume that you want to add the following transaction attributes:

master_name for all master sequences (type: vr_xbus_master_sequence) prevent_test_done and drain_time for master root sequences (type: MAIN
vr_xbus_master_sequence) You could do it as follows:
extend vr_xbus_master_sequence { get_traced_field_names() : list of string is { result.add("master_name"); }; }; extend MAIN vr_xbus_master_sequence { get_traced_field_names() : list of string is also { result.add("prevent_test_done"); result.add("drain_time"); }; };

5.12.5

Working in ASCII Mode

For efcient debugging, it is best to work in Specview. When working in ASCII mode, the Sequence Browser windows are not available. Nevertheless, in ASCII mode, you can get most details about sequences by issuing the show sequence command or by printing a sequence or sequence driver. For example:

To print a summary of all sequence drivers:


show sequence

To print a summary of all sequence drivers in the unit sys.atm_env:


show sequence sys.atm_env

To print debug information for a specic sequence:


show sequence ex_atm_sequence-@2

To print debug information for a specic sequence driver:


show sequence ex_atm_sequence-@3

When printing the sequence or sequence driver, detailed information on the sequence or sequence driver is shown at the end of the regular output.
5-92
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Working in ASCII Mode

Example 1

: Debug Information for a Sequence

---- Debug Information: ---------------------Enclosing Env: packet_env-@0 Driver: packet_driver-@1 Sequence type: BFM State: In body() Activation Mode: done Parent Sequence: PARALLEL_SORT packet_virtual_sequence-@12 Items Sent: 0 Grabbing Driver: No Comments: Trace level of driver is on. all details are available. ---- Debug Information: ----------------------

Example 2

: Debug Information for a Sequence Driver

---- Debug Information: ---------------------Enclosing Env: packet_env-@0 Driver Type: BFM State: Item in BFM Grabbing Sequence: NONE Number of Items Sent: 0 Number of do in queue: 1 Current Item: SINGLE packet-@15 Tracing level: on Wave: Off Comments: Trace level is on. all details are available. No sequence threads under driver currently. Current do: source: do packet keeping { at line 73 in @pack* done by: GROUP packet_sequence-@11 state: In BFM item: SINGLE packet-@15 belongs to grabber: N/A Pending Dos: 0. source: do packet keeping { at line 73 in @pack* done by: GROUP packet_sequence-@14 belongs to grabber: N/A ---- Debug Information: ----------------------

Note To get full information, the trace level must be log_only or on.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-93

Sequences: Constructing Test Scenarios


show sequence

5.12.6
Syntax

show sequence

sh[ow] seq[uence] [-ascii] [sequence-name| driver-name | driver-idx | unit-name] sh[ow] seq[uence] [-ascii] -log [sequence-name| driver-name| driver-idx]

Description
This command displays debugging information and activates the Sequence Browser. The command can be issued at any time during the run.

Parameters
-ascii -log Force textual output, even in GUI mode. Show the history log (the trace list) of a specied sequence or sequence driver. With this option, you must specify sequence-name, driver-name, or driver-idx. You must not specify unit-name. Show the window of the specied sequence. In ASCII mode, show debug information in text format. driver-name Show the window of the specied sequence driver. In ASCII mode, show debug information in text format. driver-idx Shows the window of the sequence driver with driver-idx, driver with the specied index in relation to all drivers under sys. To locate a driver index, issue the show sequence command with no arguments. Show the Env Sequences window of the specied unit. This displays all sequence drivers of the unit. In ASCII mode, show textual output of all sequence drivers in this unit. The default (when no parameter is provided) is to open the Env Sequences window of sys.

sequence-name

unit-name

Examples Print a summary of all sequence drivers under sys in textual output:
show seq -ascii
5-94
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Sequence-Related Actions

Open a stripe chart window with the trace list of driver number 1:
show seq -trace_list 1

Open the window of ex_atm_sequence-@23:


show seq ex_atm_sequence-@23

Open the window of ex_atm_sequence_driver-@3:


show seq ex_atm_sequence4_driver-@3

Open the Env Sequences window, displaying all sequence drivers under sys.packet_env:
show seq sys.packet_env

Open the Env Sequences window, displaying all sequence drivers under sys
show seq

5.13 Sequence-Related Actions


This section includes:

do on page 5-95 do_and_grab on page 5-97

5.13.1
Syntax

do

do eld_name [keeping {constraint;...}]

Parameters
eld_name constraint Must be a eld in the current struct. The eld must have an exclamation mark (!) in front of it and must be either a basic item or a sequence. Can be any constraints on the eld.

Description
The do action performs the following steps:

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-95

Sequences: Constructing Test Scenarios


do

On a subsequence

1. 2.

Generates the eld, considering the constraints, if any. Calls its body() TCM. The do action nishes when the subsequence body() returns.

For more information, see Figure 5-17 on page 5-121. On an item 1. 2. Waits until the driver is ready to perform the do action. Generates the eld, considering the constraints, if any.

The item is returned by get_next_item(). The do action nishes when emitting the event driver.item_done. For more information, see Figure 5-19 on page 5-123 and Figure 5-18 on
page 5-122.

Notes When do-ing an item, you must emit the event driver.item_done to let the sequence complete the do
action and inform the driver that the item was processed. (Typically, this is done when the transmission of the item via the BFM is done.) Without emitting this event, the sequence cannot continue, and the driver cannot drive more items.

The do action can only be activated inside sequences. For items, Step 1 (waiting for the sequence driver to be ready) is performed before Step 2 (generation)
to ensure that generation is done as close as possible to the actual driving. In this way, if the constraints depend on the current status of the DUT/environment, that status will be as accurate as possible.

BFM sequences cannot do sequences created by other sequence statements. The sequence driver decides when the item is ready by managing a FIFO that also considers any
grab/ungrab actions done by the various sequences and the value of is_relevant() of the sequences. If no grab is done, and is_relevant() returns TRUE for all sequences, the order of doing the items is determined by the order of the do actions in the various sequences that refer to the sequence driver, regardless of their depth or origin. Keep in mind that sequences and items can also be done in parallel, using the all of and rst of actions. (See grab() on page 5-101 and is_relevant() on page 5-105.)

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


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

5-96
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


do_and_grab

Example
extend // i: b: FOO ex_atm_sequence { Parameters int; bool;

// Items/subsequences !cell: ex_atm_cell; !seq: bar ex_atm_sequence; // The body() method body() @driver.clock is { do cell keeping {.len == 4}; do cell; for i = 1 to 20 do { do cell keeping {.address == i}; }; do seq keeping {.f == 2}; }; };

5.13.2
Purpose

do_and_grab

This action executes a do action and a grab() method simultaneously.

Syntax
do_and_grab eld_name [keeping {constraint;...}]

Parameters
eld_name constraint Must be a non-generatable basic item in the current struct. In other words, the eld represents a sequence item and not a sequence. Can be any constraints on the eld.

Description
The do_and_grab action differs from a normal do action in that it also grabs the do-ing sequences driver.
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-97

Sequences: Constructing Test Scenarios


Sequence-Related Methods

The do_and_grab action differs from a regular grab() as follows. When a regular grab() occurs, the attempt to lock the driver is immediate. With do_and_grab, no grabbing is attempted until the driver starts handling the item.

Notes If get_next_item() terminates before returning the item done by do_and_grab, the grab still takes
effect.

Example
... do_and_grab my_item; do my_item keeping {.x==BLUE;}; do another_item; ungrab(driver); ...

See Also do on page 5-95 grab() on page 5-101

5.14 Sequence-Related Methods


This section includes:

start_sequence() on page 5-99 stop() on page 5-100 grab() on page 5-101 ungrab() on page 5-102 is_blocked() on page 5-103 is_grabbed() on page 5-103 current_grabber() on page 5-104 is_relevant() on page 5-105 last() on page 5-105 branch_terminated() on page 5-107
5-98
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


start_sequence()

has_do_available() on page 5-107

5.14.1
Purpose

start_sequence()

This method of any_sequence is used to initiate the run of a sequence.

Syntax
[sequence-exp.]start_sequence()

Parameters
None

Description
start_sequence() is a non-time-consuming method that starts the body() TCM of the sequence. Use this method instead of starting the body() TCM directly. When doing so, a new sequence tree is executed.

Notes The start_sequence() of the MAIN sequence is called automatically by the driver. Before calling the start_sequence() of all sequences other than the MAIN sequence, you must
generate the sequence and connect the driver to the sequence using either a constraint or procedural code.

The parent_sequence eld of a started sequence is NULL. A started sequence has no parent sequence,
because it serves as the root of a new sequence tree.

See Also Figure 5-16 on page 5-120

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-99

Sequences: Constructing Test Scenarios


stop()

5.14.2
Purpose

stop()

This method of any_sequence is used to terminate the run of a sequence.

Syntax
[sequence-exp.]stop()

Parameters
None

Description
stop() is a non-time-consuming method that terminates the execution of body() (if such exists) by killing its thread. This might become useful if, for example, you want to terminate a sequence in the middle upon interrupt and execute an alternative sequence instead.

Notes Stopping a sequence also stops its containing tree. To stop only the sequences subsequence tree,
make sure that the sequence is started (not done) by its parent sequence.

Stopping is done on a cycle boundary, so some non-time-consuming actions in the stopped sequence
might still be executed after the sequence itself was stopped.

When stopping a sequence, the event stopped is emitted both for the stopped sequence and its root. When a sequence is stopped, it and all of its subsequences are released from the grab. For correct behavior of stop() for virtual sequences, make sure that the method get_sub_drivers()
of the virtual driver is implemented correctly and returns all BFM drivers to which the sequence and its subsequences might send items. This is also important when stopping a BFM sequence that was done by a virtual sequence. For more information about virtual sequences, see Using Virtual Sequences on page 5-23.

5-100
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


grab()

5.14.3
Purpose

grab()

This method of any_sequence lets sequences have an exclusive control over a sequence driver.

Syntax
[sequence-exp.]grab(driver) @sys.any

Parameters
driver A BFM sequence driver expression

Description
grab() is a blocking TCM that grants its calling sequence an exclusive access to driver. A sequence that wants exclusivity can call grab(driver). This grants exclusive access to that sequence and its subsequences from the moment grab() returns (perhaps, after a slight delay) until the sequence calls a corresponding ungrab(driver). During this grabbing period, the sequence driver belongs to the sequence. The driver drives only the items that were done by the grabbing sequence or its subsequences. When a sequence driver belongs to a sequence, only that sequence can send items to the sequence driver. All other sequences are blocked from sending (that is, their items remain blocked).

Notes Virtual drivers cannot be grabbed, because they do not schedule items. Sequence drivers cannot be grabbed while they execute a do action on a sequence item. The grab is
granted immediately after the completion of the do action.

Exclusive control means that the sequence and all its subsequences can use the sequence driver. All
other calls are blocked until ungrab().

When grabbing a sequence driver, make sure that the is_relevant() method of the sequence that grabs
the driver returns TRUE. This averts a situation in which the driver cannot send items.

grab() is hierarchical. If a sequence s1 grabs the sequence driver and then a sequence s2 enclosed
by s1 also grabs the sequence driver, there will be no delay as long as s2 has the sequence driver within s1. So, for example, s3 (the brother of s2) cannot access the sequence driver. Only when s2 ungrabs does s3 nally get access, but everything outside s1 is still blocked.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-101

Sequences: Constructing Test Scenarios


ungrab()

grab() is somewhat similar to lock(), but it is different in the following respects: grab() is hierarchical. grab() interacts with how items are sent. Rerunning a driver cancels the grab. If a sequence grabbed the driver before driver.rerun() was
called, the sequence must regrab the driver. If a sequence was blocked while waiting to get the grab, then it is released without grabbing the driver. For more information, see Resetting and Rerunning Sequences on page 5-37.

See Also grab_test.e in the ex_atm/examples directory (an example of grabbing and ungrabbing) ungrab() on page 5-102

5.14.4
Purpose

ungrab()

This method of any_sequence stops sequences from having an exclusive control over a sequence driver.

Syntax
[sequence-exp.]ungrab(driver)

Parameters
driver A BFM sequence driver expression

Description
ungrab() is a non-time-consuming method that releases the driver from the exclusive control of the sequence that was previously granted by calling grab().

Notes A virtual driver cannot be ungrabbed, because it does not schedule items. Calling ungrab() when a sequence did not grab the driver results in error.

5-102
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


is_blocked()

See Also grab_test.e in the ex_atm/examples directory (an example of grabbing and ungrabbing) grab() on page 5-101

5.14.5
Purpose

is_blocked()

This method is valid for BFM sequences only. It indicates whether a sequence is blocked from sending items. It happens when another sequence that is not an ancestor has grabbed the sequence driver.

Syntax
[sequence-exp.]is_blocked(): bool

Parameters
None

Description
is_blocked() is a non-time-consuming method that returns TRUE if the sequence is blocked by another sequence that grabbed the sequence driver.

See Also grab() on page 5-101

5.14.6
Purpose

is_grabbed()

This method is valid for BFM sequence drivers only. It indicates the grab status of the sequence driver.

Syntax
[driver-exp.]is_grabbed(): bool

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-103

Sequences: Constructing Test Scenarios


current_grabber()

Parameters
None

Description
is_grabbed() is a non-time-consuming method that returns TRUE if the sequence driver is grabbed by a sequence.

See Also grab() on page 5-101

5.14.7
Purpose

current_grabber()

This method is valid for BFM sequence drivers only. It indicates which sequence (if any) has exclusive control over a sequence driver.

Syntax
[driver-exp.]current_grabber(): any_sequence

Parameters
None

Description
current_grabber() is a non-time-consuming method that returns the sequence that currently has exclusive control over the sequence driver. It returns NULL if no sequence currently has exclusive control over the sequence driver.

See Also grab() on page 5-101

5-104
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


is_relevant()

5.14.8
Purpose

is_relevant()

This method is valid for BFM sequences only. It indicates whether the sequence is currently relevant for do-ing items.

Syntax
[sequence-exp.]is_relevant(): bool

Parameters
None

Description
is_relevant() is a non-time-consuming method that returns TRUE if the sequence is currently allowed to do items. By default, this method returns TRUE. You can implement it to respond to the changing conditions of the simulation. It is particularly useful for sequences used by reactive agents.

5.14.9
Purpose

last()

This method is valid for BFM sequence drivers only. It enables access to previously sent items in the sequence driver.

Syntax
[driver-exp.]last(index): item

Parameters
index The index in the sequence history. 0 is the currently sent item, 1 is the previous item, and so on.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-105

Sequences: Constructing Test Scenarios


last()

Return Value
item The item that was created index items ago by the sequence. The return value is NULL if such item does not exist.

Description
last() is a non-time-consuming method that lets you directly access items in the history of the sequence:

last(0) returns the item currently being driven in (or the last item that was driven in, if there is no
item currently being driven in).

last(1) returns the item before last(0), and so on.


The length of the history is determined by the eld num_of_last_items in the sequence driver, which can be constrained by the user. The default is 1.

Notes last(i) results in an error if i >= num_of_last_items. The maximum value for num_of_last_items is 1024. num_of_last_items is a static property of the BFM driver. Therefore, it cannot be changed during the
run.

Example 1
You could create a sequence that alternates colors from red to green as follows:
extend packet { keep color == (driver.last(0) is a GREEN packet ? RED : GREEN); };

Example 2
You could congure the buffer to store the last 10 items (instead of the default 1 item) as follows:
extend packet_seq_driver { keep num_of_last_items == 10 };

Notes The is a construct is a convenient way to also avoid checking for non-NULL.

5-106
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


branch_terminated()

For efciency, in the sequence driver you might want to set Boolean ags that summarize the last()
information. In that case, the constraint can refer to the Boolean ags rather than last().

You can also use last()-based constraints in sequences (not just items). The last() buffer is cleared upon driver.rerun().

5.14.10 branch_terminated()
Purpose
This method of any_sequence_driver is relevant when performing a do action inside a rst of block.

Syntax
[driver-exp.]branch_terminated()

Parameters
None

Description
This method lets you resume normal operation in the current cycle when a do action in a rst of block terminates prematurely.

See Also Using Sequences from a rst of Block on page 5-13

5.14.11 has_do_available()
Purpose
This method of any_sequence_driver tells an inquiring BFM if a do is available for execution.

Syntax
[driver_exp.]has_do_available(): bool

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-107

Sequences: Constructing Test Scenarios


Sequence-Related Pseudo-Routines

Parameters
None

Description
This method of any_sequence_driver returns TRUE if the driver can execute a do immediately. This can only happen when the following conditions are met:

The driver is not already busy handling a do (because the driver can only handle one do at a time). The driver has in its queue at least one relevant do (that is, its parent sequence returns TRUE for
is_relevant()).

The relevant do is not blocked (because another sequence has grabbed the driver).
Note Even when has_do_available() returns TRUE, an item might not be returned immediately by get_next_item(). It depends on the pre_do() TCM.

Example
... if my_driver.has_do_available() { var an_item := my_driver.get_next_item(); }; ...

5.15 Sequence-Related Pseudo-Routines


This section includes:

in_sequence() on page 5-108 in_unit() on page 5-109

5.15.1

in_sequence()

This pseudo-routine can be used inside sequences and items.

Syntax
[exp.]in_sequence(sequence_type) [(name)]

5-108
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


in_unit()

Parameters
exp sequence_type name An item, sequence, or a BFM sequence driver expression. If exp is missing, me is used. Any type or subtype of a sequence (that is, it inherits from any_sequence). Reference for the found sequence.

Description
The in_sequence() routine returns TRUE if exp is an item or a sequence that was created using do inside a sequence of type sequence_type (at any depth). If name is specied, it assigns the found sequence to name. If exp is a BFM sequence driver sd, then in_sequence() returns TRUE if sd.last(0) returns TRUE. in_sequence() can be used in constraints to determine whether an item is inside a specic sequence type. This allows enforcing constraints on every item in the sequence tree under a specic sequence. Therefore, this kind of constraint is called a tree constraint. It is useful when you want to say something like: Every ATM cell under the FOO sequence should be green, regardless of how far down it is in the hierarchy.

Example
extend ex_atm_cell { keep in_sequence(FOO ex_atm_sequence) => color == GREEN; // Implements the condition above keep in_sequence(BAR ex_atm_sequence) (B) => len == B.len1; // If this cell is somewhere under a BAR ex_atm_sequence, // then set len to this sequence's len1 field };

Of course, the in_sequence() pseudo-routine can also be used in normal procedural code. For example:
if in_sequence(BAR ex_atm_sequence) (B) then { print B.len1; };

5.15.2

in_unit()

This pseudo-routine can be used anywhere.


e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-109

Sequences: Constructing Test Scenarios


Sequence Interface

Syntax
[exp.]in_unit(unit_type) [(name)]

Parameters
exp unit_type name A struct. If exp is missing, me is used. Any type or subtype of a unit. Reference for the found unit.

Description
in_unit() returns TRUE if you are inside such a unit (at any depth). If name is specied, it assigns the found unit to name.

Note in_unit(foo) is equal to: try_enclosing_unit(foo) != NULL. The motivation behind this routine is
to make it shorter and similar to in_sequence() as well as to enable tree constraints.

See Also Writing Tests Using Sequences on page 5-18

5.16 Sequence Interface


The sequence model consists of: item sequence driver Inherits from any_sequence_item Inherits from any_sequence so that any sequence struct that you create has both the any_sequence interface and the any_sequence_item interface Inherits from any_sequence_driver

The following tables contain the full list of methods and elds for any_sequence_item Interface, any_sequence Interface, and any_sequence_driver Interface.

5-110
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Sequence Interface

Table 5-15 any_sequence_item Interface Struct Member Description

Read Only Member (can only be accessed)

get_depth(): int get_driver(): driver_name !parent_sequence: any_sequence; do_location(): string

Depth from the sequence driver, valid from pre-generation. Returns the driver for an item. Backpointer to the sequence in which an item was created. Assigned automatically in the pre_generate() of the item. Returns a string describing the source location of the do action that generated the current item. Not relevant for sequence_items not created via the do action.

Read/Write Member (can also be set, constrained, or implemented)

driver: driver_name nice_string(): string is empty

Driver for the item, soft-constrained to be its parent sequences driver. A short string representing the item for tracing. It is used by trace sequence, wave sequence, and show sequence (see Tracing and Debugging Sequences on page 5-70). The default implementation returns the value of to_string().

Notes

The information in this section also applies to sequences. The driver eld is not dened in any_sequence_item. For this eld to be dened, you must use the
item in a sequence statement.

The get_driver() method is declared as undened in any_sequence_item. For this method to be


dened, you must use the item in a sequence statement.

Never use is only on the pre_generate() or post_generate() of items or sequences. The


parent_sequence and driver of elds are assigned in the pre_generate() of any_sequence_item. Table 5-16 any_sequence Interface Struct Member Description

Read Only Member (can only be accessed)

get_depth(): int

Depth from the sequence driver, valid from pre-generation.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-111

Sequences: Constructing Test Scenarios


Sequence Interface

Table 5-16 any_sequence Interface (continued) Struct Member get_driver(): driver_name !parent_sequence: any_sequence; get_index(): int grab(driver: any_sequence_driver) @sys.any is undened is_blocked(): bool is_relevant(): bool start_sequence() Description Return the driver for a sequence. Backpointer to the sequence in which this sequence was created. Assigned automatically in pre_generate() of the sequence if such a parent exists. Starts at 0 and gets incremented after every do. Provides a declarative style. Grab the sequence driver for exclusive access and returns when you have exclusive access. Indicate whether the sequence is blocked. Apply a condition for performing a do item action, so that the do action will not be scheduled until is_relevant() returns TRUE. Starts sequence activity by starting body(). Note Call this method instead of starting body() directly. See also Figure 5-16 on page 5-120. stop() ungrab(driver: any_sequence_driver) is undened Terminates my body(), if it exists. Releases the grab on a sequence driver and returns immediately.

Read/Write Member (can also be set, constrained, or implemented)

driver: driver_name nice_string(): string is empty

Driver for the sequence, soft-constrained to be its parent sequences driver. A short string representing the sequence for tracing. It is used by trace sequence, wave sequence, and show sequence (see Tracing and Debugging Sequences on page 5-70). The default implementation returns the kind followed by the instance name (for example, RED atm_sequence-@2).

@ended @started

Emitted immediately after body() is nished. Emitted just before body() is called.

5-112
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Sequence Interface

Table 5-16 any_sequence Interface (continued) Struct Member body() @driver.clock is empty kind: kind_name mid_do(s: any_sequence_item) is empty; post_body() @sys.any is empty; post_do(s: any_sequence_item) is empty; post_do_tcm(s: any_sequence_item) @sys.any is empty; post_trace() pre_body() @sys.any is empty; pre_do(is_item: bool) @sys.any is empty; Description Main method called by do of parent sequence after it generates the current sequence. The kind eld that determines which sequence it is (within its when family). Hook method called in the middle of do, just after s is generated and before it is executed by calling the body() TCM. Hook method called after body() when sequence is started using the start_sequence() method. Hook method called at end of do, just after the execution of s.body().

Hook TCM called after post_do(). Extends the life of a do after the item_done event is emitted. The sequence driver, freed by the item_done event, no longer manages the current item. It can handle other items. Gets called for every sequence just after a trace message about it gets printed. (Useful for breakpoints.) Hook method called before body() when sequence is started using the start_sequence() method. Hook TCM called at start of a do performed by the sequence. is_item species whether you are in a context of do-ing an item or a sequence.

Note Some of the methods in Table 5-16 above are inherited from the any_sequence_item interface shown in Table 5-15 on page 5-111. Table 5-17 any_sequence_driver Interface Struct Member Description BFM Only

Read Only Member (can only be accessed)

current_grabber(): any_sequence

Indicates which sequence (if any) has exclusive control over a sequence driver.

Yes

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-113

Sequences: Constructing Test Scenarios


Sequence Interface

Table 5-17 any_sequence_driver Interface (continued) Struct Member get_current_item(): any_sequence_item get_index(): int get_item_trace_list(): list of any_sequence_item Description Returns the item currently being sent. (NULL if the BFM is currently idle.) Returns index of this sequence driver in the all-driver list. Returns a list of the items handled (sent) by the sequence driver (the item sublist of the trace log). Note The list is populated only if the trace sequence command was activated in On or Log Only mode. get_next_item(): item_name @clock This TCM should be called in PULL_MODE to receive the next item from the BFM driver. This TCM is blocked until there is an item to do in the driver. See also Figure 5-19 on page 5-123. get_num_items_sent(): int get_sequence_trace_list(): list of any_sequence Returns count of items sent (excluding current_item, if any). Returns a list of the sequences handled by the sequence driver (the sequence sublist of the trace log). Note The list is populated only if the trace sequence command was activated in On or Log Only mode. get_trace_list(): list of any_sequence_item Returns a list of all sequences and items handled by the sequence driver (the full trace log). Note The list is populated only if the trace sequence command was activated in On or Log Only mode. is_grabbed(): bool last(index): any_sequence_item Indicates the grab status of the sequence driver. Enables access to previously sent items in the sequence driver. Yes Yes Yes Yes Yes Yes BFM Only Yes No Yes

5-114
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Sequence Interface

Table 5-17 any_sequence_driver Interface (continued) Struct Member try_next_item(): item_name @clock Description This TCM should be called in PULL_MODE when the BFM has to receive an item or perform some default behavior. Unlike get_next_item(), in case there is no available item waiting to be done in the current cycle, this TCM returns NULL. Note try_next_item() returns in the same cycle if there is no pending do action. However, if a do action started execution, then try_next_item() might take longer than a cycle, for example, if you extend the pre_do() TCM to take longer than a cycle. See also Figure 5-20 on page 5-124.
Read/Write Member (can also be set, constrained, or implemented)

BFM Only Yes

bfm_interaction_mode: bfm_interaction_mode_t

Species the way the driver and the BFM interact with each other. Possible options are PULL_MODE (the default) and PUSH_MODE. It can be constrained. See also BFM-Driver Interaction Mode on page 5-43.

Yes

max_random_count: int

Used in setting the maximum number of subsequences in a RANDOM or MAIN sequence.


keep soft max_random_count == MAX_RANDOM_COUNT; // Defined to // be 10

No

max_random_depth: int

Used for setting the maximum depth inside RANDOM sequences. (Beyond that depth, RANDOM creates only SIMPLE sequences.)
keep soft max_random_depth == MAX_RANDOM_DEPTH; // Defined // to be 4

No

num_of_last_items: int

Used for setting the length of the history of previously sent items. Default is 1.

Yes

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-115

Sequences: Constructing Test Scenarios


Sequence Interface

Table 5-17 any_sequence_driver Interface (continued) Struct Member gen_and_start_main: bool Description Enable or disable automatic generation and launch of the MAIN sequence upon run. Default is TRUE (MAIN sequence is generated and started). For forcing a driver to recheck the relevance (value of is_relevant()) for each sequence that has items in the drivers item queue. It can be useful when something has changed in the BFM that affects the relevance of some sequences. This TCM can be used to emit the drivers clock with some intercycle delay to let the BFM export its state before activation of sequences in a specic cycle. Note This TCM should be activated INSTEAD of connecting the clock to another event. event clock The main clock. Should be tied to some temporal formula by users during the sequence driver hooking. Synchronization event for the do action in PULL_MODE. When working in PULL_MODE, you must emit this event to complete the do item and let the driver get more items using get_next_item(). See also Sequence Driver Unit on page 5-7. get_sub_drivers(): list of any_sequence_driver is empty For virtual sequence drivers, this method is to be lled in by the writer of the specic sequence driver. It should return the list of subdrivers of the sequence driver. For a BFM sequence driver, it should be left unchanged, that is, return an empty list. For implementing a DUT-independent interface. See also: DUT-Independent Read/Write Interface on page 5-39 Virtual only No BFM Only No

check_is_relevant()

Yes

delay_clock() @sys.any

No

event item_done

Yes

read(address: list of bit): list of bit @clock is undened;

No

5-116
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Predened Sequence Kinds

Table 5-17 any_sequence_driver Interface (continued) Struct Member regenerate_data() is empty Description Regenerates drivers data upon rerun(). See also Resetting and Rerunning Sequences on page 5-37. send_to_bfm(seq_item: item_name) @clock is empty When working in PUSH_MODE, sends the item to the corresponding BFM. To be implemented by users as part of hooking. This method is called automatically (when working in PUSH_MODE). wait_for_sequences() @sys.any This TCM is called to delay the return of try_next_item() and let sequences create items. It can also be called in other locations to help propagation of activity (for example, among several layers of sequences). It can also be overridden to implement a different scheme than the default one. For implementing a DUT-independent interface. See also DUT-Independent Read/Write Interface on page 5-39. Yes Yes BFM Only No

write(address: list of bit, data: list of bit) @clock is undened;

No

Notes

Some of the driver members are relevant only for BFM drivers. See the last column in the table above. Never use is only on the pre_generate() or post_generate() of drivers. The list of previously sent
items of the driver is initialized in the post_generate() of the driver.

Never use is only on the run() or rerun() of drivers. Some important initializations are performed
in those methods.

5.17 Predefined Sequence Kinds


There are three predened sequence kinds: MAIN, RANDOM, and SIMPLE. The following sections describe their implementation.

MAIN Sequence on page 5-118


e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-117

Sequences: Constructing Test Scenarios


MAIN Sequence

RANDOM Sequence on page 5-118 SIMPLE Sequence on page 5-119

5.17.1

MAIN Sequence

This sequence subtype is dened directly under the sequence driver and is started by default. It is used as the root for the whole sequence tree.
extend MAIN sequence_name { count: uint; !sequence: sequence_name; keep soft count > 0; keep soft count <= MAX_RANDOM_COUNT; keep sequence.kind not in [RANDOM, MAIN]; body() @driver.clock is only { for i from 1 to count do { do sequence; }; }; };

5.17.2

RANDOM Sequence

This sequence subtype is used for creating random scenarios based on SIMPLE and user-dened sequence subtypes.
extend RANDOM sequence_name { count: uint; !sequence: sequence_name; keep keep keep keep soft count > 0; soft count <= MAX_RANDOM_COUNT; sequence.kind not in [RANDOM, MAIN]; depth_from_driver >= driver.max_random_depth => sequence.kind == SIMPLE;

body() @driver.clock is only { for i from 1 to count do { do sequence; }; }; };

5-118
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


SIMPLE Sequence

5.17.3

SIMPLE Sequence

This sequence subtype generates and executes a single item.


extend SIMPLE sequence_name { !seq_item: item; body() @driver.clock is only { do seq_item; }; };

5.18 BFM-Driver-Sequence Flow Diagrams


This section contains diagrams to show how the BFM, the driver, and the sequences interact with each other:

sequence.start_sequence() Flow on page 5-120 do Subsequence Flow on page 5-121 do Item Flow in Push Mode on page 5-122 do Item Flow in Pull Mode Using get_next_item() on page 5-123 do Item Flow in Pull Mode Using try_next_item() on page 5-124

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-119

Sequences: Constructing Test Scenarios


sequence.start_sequence() Flow

5.18.1

sequence.start_sequence() Flow
Sequence Driver Sequence start_sequence()
- Parent sequence is NULL. - Sequence is already generated. - Driver is not NULL.

Figure 5-16 sequence.start_sequence() Flow

The sequence driver does not schedule sequences but only items. Therefore, when starting a sequence, no synchronization is done between the driver and the started sequence.

trace: Starting sequence. sequence is added to the drivers trace list. emit @started.

Start TCM that:


- Calls pre_body() TCM - Calls body() TCM - Calls post_body() TCM emit @ended.

Return of start_sequence()

Note This ow does not depend on the bfm_interaction_mode


Figure 5-16 describes the ow when starting a sequence using the start_sequence() method.

For more information on the start_sequence() method, see start_sequence() on page 5-99.

5-120
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


do Subsequence Flow

5.18.2

do Subsequence Flow
Sequence Driver (driver) (1) Sequence (n) do subsequence Call pre_do() TCM, with is_item = FALSE Generate subsequence with:
- parent_sequence = sequence - driver = sequence.driver (by constraint)

Figure 5-17 do Subsequence Flow

The sequence driver does not schedule sequences but only items. Therefore, when do-ing a sequence, no synchronization is done between the driver and the doing sequence or the done subsequence.

subsequence is added to the drivers trace list

Trace: subsequence created Call mid_do() Emit @subsequence.started Call subsequence.body() Emit @subsequence.ended Trace: subsequence done Call post_do() End of do subsequence

Note This ow does not depend on the bfm_interaction_mode.


Figure 5-17 describes the ow when do-ing a subsequence.

For more information on the do action, see Activating Items and Subsequences on page 5-13.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-121

Sequences: Constructing Test Scenarios


do Item Flow in Push Mode

5.18.3
BFM (1)

do Item Flow in Push Mode


Driver (1)
Choose a do action to be executed on a rst-come-rst-served basis, considering grabbers, and sequence.is_relevant() Acknowledge the sequence

Figure 5-18 do Item Flow in Push Mode


Sequence (n)
do item The do action is listed in the drivers queue Wait for the driver acknowledgement Call pre_do() TCM, with is_item = TRUE Generate item with:
- parent_sequence = sequence - driver = sequence.driver (by constraint)

Wait until item is generated

Sends item to DUT

Call send_to_bfm(item) Emit @item_done

item is added to the drivers trace list Trace: item created Call mid_do() Add item to drivers last() buffer Acknowledge the driver that item is ready to be sent Wait for @driver.item_done Trace: item sent by driver Call post_do() End of do item

Note This ow occurs when driver.bfm_interaction_mode == PUSH_MODE


Figure 5-18 describes the ow when do-ing an item when driver.bfm_interaction_mode is set to PUSH_MODE.

For more information on the do action, see Activating Items and Subsequences on page 5-13. For more information on driver.bfm_interaction_mode, see Hooking the Sequence Driver to the Environment on page 5-9.

5-122
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


do Item Flow in Pull Mode Using get_next_item()

5.18.4
BFM

do Item Flow in Pull Mode Using get_next_item()


Driver
Choose a do action to be executed on a rst-comerst-served basis, considering grabbers, and sequence.is_relevant() Acknowledge the sequence

Figure 5-19 do Item Flow in Pull Mode Using get_next_item()


Sequence do item
The do action is listed in the drivers queue Wait for the driver acknowledgement Call pre_do() TCM, with is_item = TRUE Generate item with:
- parent_sequence = sequence - driver = sequence.driver (by constraint)

Call driver.get_next_item()

Wait until item is generated

Sends item to DUT Emit @item_done

Get next_item() returns

item is added to the drivers trace list Trace: item created Call mid_do() Add item to drivers last() buffer Acknowledge the driver that item is ready to be sent Wait for @driver.item_done Trace: item sent by driver Call post_do() End of do item

Note This ow occurs when driver.bfm_interaction_mode == PULL_MODE.


Figure 5-19 describes the ow when do-ing an item when driver.bfm_interaction_mode is set to PULL_MODE and driver.get_next_item() is used to receive items from the driver.

For more information on the do action, see Activating Items and Subsequences on page 5-13. For more information on driver.bfm_interaction_mode, see Hooking the Sequence Driver to the Environment on page 5-9. For more information on driver.get_next_item(), see Table 5-17 on page 5-113.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-123

Sequences: Constructing Test Scenarios


do Item Flow in Pull Mode Using try_next_item()

5.18.5

do Item Flow in Pull Mode Using try_next_item()


BFM
Call driver.try_next_item()

Figure 5-20 do Item Flow in Pull Mode Using try_next_item()


Driver
First of: { choose a do action } { wait_for_sequences() } A do action is chosen before wait_for_sequences returns?

No

Yes

try_next_item()
returns with NULL Create a default item Send item to the DUT Continue as in

get_next_item()
ow.

try_next_item()
returns an item.

Notes

This ow occurs when driver.bfm_interaction_mode == PULL_MODE try_next_item() might take more than a cycle, in case a do is chosen and pre_do() takes more than a cycle

Figure 5-20 describes the ow when do-ing an item when driver.bfm_interaction_mode is set to PULL_MODE and driver.try_next_item() is used to receive items from the driver.

For more information on the do action, see Activating Items and Subsequences on page 5-13. For more information on driver.bfm_interaction_mode, see Hooking the Sequence Driver to the Environment on page 5-9. For more information on driver.try_next_item(), see Applying Default Behavior When No Item Is Done
on page 5-51 and Table 5-17 on page 5-113.

5.19 Sequence Deprecation


This section contains:

Method sequence.start() Deprecation on page 5-125

5-124
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Method sequence.start() Deprecation

Field sequence Deprecation on page 5-125 Sequence item Deprecation on page 5-127

5.19.1

Method sequence.start() Deprecation

All sequences currently have a method named start(). As start is now an e keyword, the name of this method must be changed to something that does not conict. Therefore, from Specman 4.3, the start() method of any_sequence changes to start_sequence(). Note Currently the default severity of this deprecation is IGNORE. You will not get any warning or error message unless you change the severity level.

Associated Notication IDs


DEPR_SEQUENCE_START_KEYWORD

Sample Notication Message


If any sequence uses the start() method and you have set the severity level to WARNING, you will receive a message like the following:
*** Warning: DEPR_SEQUENCE_START_KEYWORD: The keyword 'start' is used as an identifier. Replace the method any_sequence.start() with any_sequence.start_sequence() at line 50 in @seq my_sequence.start(); For more information, search help for 'DEPR_SEQUENCE_START_KEYWORD'.

For more information on the deprecation process, see The Deprecation Process for Syntactic Changes in the e Language Reference.

5.19.2

Field sequence Deprecation

MAIN and RANDOM sequences currently have a eld named sequence. As sequence is now an e keyword, the name of this eld must be changed to something that does not conict. From Specman 4.3, the sequence eld changes as follows:

The name of the MAIN sequence eld under a sequence driver changes from sequence to
main_sequence.

Under the MAIN sequence, the name of the eld sequence changes to sub_sequence. Under the RANDOM sequence, the name of the eld sequence changes to sub_sequence.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-125

Sequences: Constructing Test Scenarios


Field sequence Deprecation

Note Currently the default severity of this deprecation is IGNORE. You will not get any warning or error message unless you change the severity level. To use the new eld names:

Constrain the sequence driver ag using_new_sequence_naming to TRUE.


keep using_new_sequence_naming == TRUE;

This enables the new names for the sequence eld in the driver and its associated sequences.

Associated Notication IDs


DEPR_SEQUENCE_FIELD_KEYWORD

Sample Notication Message


If your code uses the old name for the MAIN sequence eld under a sequence driver and you have set the severity level to WARNING, you will receive a message like the following:
*** Warning: DEPR_SEQUENCE_FIELD_KEYWORD The keyword 'sequence' is used as an identifier. Replace 'sequence' of my_sequence_driver with 'main_sequence' after constraining my_sequence_driver.using_new_sequence_naming to TRUE. For more information, search help for 'DEPR_SEQUENCE_FIELD_KEYWORD'

If your code uses the old sequence eld name under MAIN and you have set the severity level to WARNING, you will receive a message like the following:
*** Warning: DEPR_SEQUENCE_FIELD_KEYWORD The keyword 'sequence' is used as an identifier. Replace 'sequence' of MAIN'kind my_sequence with 'sub_sequence' after constraining my_sequence_driver.using_new_sequence_naming to TRUE. For more information, search help for 'DEPR_SEQUENCE_FIELD_KEYWORD'

If your code uses the old sequence eld name under RANDOM and you have set the severity level to WARNING, you will receive a message like the following:
*** Warning: DEPR_SEQUENCE_FIELD_KEYWORD The keyword 'sequence' is used as an identifier. Replace 'sequence' of RANDOM'kind my_sequence with 'sub_sequence' after constraining my_sequence_driver.using_new_sequence_naming to TRUE For more information, search help for 'DEPR_SEQUENCE_FIELD_KEYWORD'

For more information on the deprecation process, see The Deprecation Process for Syntactic Changes in the e Language Reference.
5-126
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Sequences: Constructing Test Scenarios


Sequence item Deprecation

5.19.3

Sequence item Deprecation

The SIMPLE sequence currently has a eld named item. As item is now an e keyword, the name of this eld must be changed to something that does not conict. Therefore, from Specman 4.3, the item eld of the SIMPLE sequence changes to seq_item. Note Currently the default severity of this deprecation is IGNORE. You will not get any warning or error message unless you change the severity level.

Associated Notication IDs


DEPR_SEQUENCE_ITEM_KEYWORD

Sample Notication Message


If the SIMPLE sequence uses the item eld and you have set the severity level to WARNING, you will receive a message like the following:
*** Warning: DEPR_SEQUENCE_ITEM_KEYWORD: The keyword 'item' is used as an identifier. Replace 'item' of SIMPLE'kind my_sequence with 'seq_item' after constraining my_sequence_driver.using_new_sequence_naming to TRUE. For more information, search help for 'DEPR_SEQUENCE_ITEM_KEYWORD'.

For more information on the deprecation process, see The Deprecation Process for Syntactic Changes in the e Language Reference.

5.20 Known Limitations


Following are the known limitations of the sequence model:

Same Item Cannot Be Used in Two Different Sequences on page 5-127 Item Children Cannot Be Created with Like Inheritance before Sequence Statement on page 5-128 Sequences Are Supported Only from Version 4.1 on page 5-128

5.20.1

Same Item Cannot Be Used in Two Different Sequences

Description
You cannot use the same item type in two different sequence statements in the same environment.

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-127

Sequences: Constructing Test Scenarios


Item Children Cannot Be Created with Like Inheritance before Sequence Statement

Workaround
Create two (or more) subtypes and use the subtypes in the sequences (a different subtype for each sequence type).

Example
You could create two different sequences for ATM cells as follows: 1. Dene the type to create the subtypes. For example:
type cell_seq_kind: [A, B];

2.

Add the type to the item for which you want to create sequences. For example:
extend ex_atm_cell { seq_kind: cell_seq_kind; };

3.

Use the sequence statement to create two different sequences for the two different subtypes. For example:
sequence atm_A using item=A ex_atm_cell; sequence atm_B using item=B ex_atm_cell;

5.20.2

Item Children Cannot Be Created with Like Inheritance before Sequence Statement

Specman does not allow the addition of elds to a struct that already has like children. The sequence statement adds elds and methods to the item struct. Therefore, if you have created like item children before the sequence statement, Specman reports an error when the sequence statement occurs.

Example
sequence my_seq using item=my_item; // Create children of my_item only after the sequence statement struct my_new_item like my_item {...}

5.20.3

Sequences Are Supported Only from Version 4.1

The sequences package can be run only on top of Specman version 4.1 or higher.
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-128

Sequences: Constructing Test Scenarios


Sequences Are Supported Only from Version 4.1

e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

5-129

Sequences: Constructing Test Scenarios


Sequences Are Supported Only from Version 4.1

5-130
2006 Cadence Design Systems, Inc. All rights reserved worldwide.

e Reuse Methodology

Das könnte Ihnen auch gefallen