Documente Academic
Documente Profesional
Documente Cultură
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
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
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.
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
...
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
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.
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
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
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
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
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
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
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
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.
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
5-7
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
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
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 { ... }; };
5.3.3
1. 2. 3. 4. 5.
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
};
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 ... }; };
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;
5-10
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.
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
Implementing a Scenario Using the Sequence Struct on page 5-12 Creating a Sequence Library on page 5-17
5.4.1
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
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:
5-12
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
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
Use the do action. See Also do on page 5-95 do_and_grab on page 5-97
5.4.1.3
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
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
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
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
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 }; };
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
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>; }; };
5.4.2
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:
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
5-17
Note Cadence recommends encapsulating any meaningful scenario as a new sequence kind. 3. Iterate Step 1 and Step 2 as required.
5.5
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
5.5.1
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
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
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
};
5.5.2.2
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
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
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
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
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
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
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
};
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
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.
5.7
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
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.
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
ethernet: ethernet_sequence_driver;
3.
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
5.7.2
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:
5.7.3
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.
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
};
5.7.4
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
DMA Controller
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
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.
5-28
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
Virtual Driver
eth_cong seq atm_sequence
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
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
5-29
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
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.
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.
e Reuse Methodology
.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
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
3.
Add an additional constraint for the root sequence in the root-sequence parent.
Example
type ex_atm_port_id: [ATM_0, ATM_1]; extend ex_atm_sequence { port_id: ex_atm_port_id; // Field to be propagated keep parent_sequence != NULL => // The propagating constraint soft port_id == parent_sequence.as_a(ex_atm_sequence).port_id; }; extend ex_atm_driver { port_id: ex_atm_port_id; keep sequence.port_id == port_id; };
5.8.3
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; };
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
5.8.4
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
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 {
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
5-33
5.9
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
Using the do action within an all of block Starting several sequences using the start_sequence() method Example 1 Using the do action
e Reuse Methodology
Example 2
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
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
... }; };
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
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
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
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.
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
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
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
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.
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.
5-40
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
// 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.
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
5.9.6
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:
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.)
5-42
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
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
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
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.
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
5.9.9
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
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
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
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
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
!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; }; }; };
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
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:
5-48
For example:
extend ex_atm_driver { keep soft gen_and_start_main == FALSE; };
5.10.2
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
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
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.
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
5.10.3
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
See Also Figure 5-20 on page 5-124 Figure 5-19 on page 5-123
5.10.4
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
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).
5-52
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
start delay_driver_clock(); }; };
Note This TCM replaces the regular clock connection, so make sure that the clock is not also emitted.
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]; }; }; };
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
5-53
5.10.5
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:
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:
e Reuse Methodology
return FALSE; }; };
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
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
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.
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
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
seq seq
Packet SD
seq
Multi-Layer Architecture
seq seq
Frame SD
seq
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.
5-58
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
5.11.2
Styles of Layering
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
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
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
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.
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
5-61
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-62
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
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
seq seq L2A SD seq seq seq L2A SD seq seq seq
L2B BFM
seq seq
L1A
seq
L1B SD
seq
seq seq
L1B BFM
5.11.3
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
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
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();
seq seq
Frame BFM
Packet SD
seq
seq seq
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
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
Note This allows conditional layering. If that is not needed, you can remove the use_layering ag and the logic around it.
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
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
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
return pack(packing.low, packet); } else { // No real packet. Therefore, return a filler result.resize(32); return result; }; }; }; -- get_payload() };
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
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
Description
This command shows the tracing mode of each sequence driver.
5-72
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
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
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
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-74
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
Note Trace lists are used when showing the stripe chart of the sequence and sequence driver.
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
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.
Syntax
wave seq[uence] [bfm-driver-num]
5-76
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
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.
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
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
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
5.12.3
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-80
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
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
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.
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
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
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
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
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)
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
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
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
5-87
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
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
Or
If there are many threads, use the Sequence Driver window to nd an interesting sequence thread to
debug with the source debugger.
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
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.
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-90
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
Example 1
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.
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
5-91
Example 2
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
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:
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
Example 1
---- 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: ---------------------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
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
Open a stripe chart window with the trace list of driver number 1:
show seq -trace_list 1
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.1
Syntax
do
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
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.)
5-96
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
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
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
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); ...
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
5.14.1
Purpose
start_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.
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
5-99
5.14.2
Purpose
stop()
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
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
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
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.
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
Parameters
None
Description
is_grabbed() is a non-time-consuming method that returns TRUE if the sequence driver is grabbed by a sequence.
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.
5-104
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
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
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).
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
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.
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
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.1
in_sequence()
Syntax
[exp.]in_sequence(sequence_type) [(name)]
5-108
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
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()
5-109
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.
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
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.
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.
get_depth(): int
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
5-111
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.
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
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
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
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
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_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
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
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
No
5-116
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
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
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-117
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;
5-118
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
5.17.3
SIMPLE Sequence
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
5.18.1
sequence.start_sequence() Flow
Sequence Driver Sequence start_sequence()
- Parent sequence is NULL. - Sequence is already generated. - Driver is not NULL.
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.
Return of start_sequence()
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
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)
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.
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
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
5.18.3
BFM (1)
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
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
5.18.4
BFM
Call driver.get_next_item()
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
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
5.18.5
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-124
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology
Field sequence Deprecation on page 5-125 Sequence item Deprecation on page 5-127
5.19.1
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.
For more information on the deprecation process, see The Deprecation Process for Syntactic Changes in the e Language Reference.
5.19.2
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
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:
This enables the new names for the sequence eld in the driver and its associated sequences.
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
5.19.3
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.
For more information on the deprecation process, see The Deprecation Process for Syntactic Changes in the e Language Reference.
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
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
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
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
e Reuse Methodology
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
5-129
5-130
2006 Cadence Design Systems, Inc. All rights reserved worldwide.
e Reuse Methodology