Home > Community > Blogs > Functional Verification > ovm e sequence api brings increased flexibility
Login with a Cadence account.
Not a member yet?
Create a permanent login account to make interactions with Cadence more convenient.

Register | Membership benefits
Get email delivery of the Functional Verification blog (individual posts).


* Required Fields

Recipients email * (separate multiple addresses with commas)

Your name *

Your email *

Message *

Contact Us

* Required Fields
First Name *

Last Name *

Email *

Company / Institution *

Comments: *

OVM-e Sequence API Brings Increased Flexibility

Comments(0)Filed under: Functional Verification, OVM, eRM, e, Specman, API

Specman 8.2s2 adds new Application Programming Interface (API) methods to sequence drivers, enabling enhanced flexibility to users working with layered protocols, users looking for performance enhancements, and more. Although this feature is still considered Early Adopter (EA), I suspect some of you sequence experts will be quite excited to begin using this feature ASAP.

Introduced years ago in eRM (now OVM-e), sequences supply a reusable way for users to define test scenarios.  Both environment developers and test writers write sequences that typically include multiple calls to the do action.  For example:



extend MY_SPECIAL_SEQ my_sequence_s {

     loop_count: uint[5..10];

     my_sequence: my_sequence_s;  

     body() @driver.clock is only {

          for i from 1 to loop_count do {

              do my_item;    // send a single item

              do my_sequence; // send a random sequence

          }; // for

     }; //body

}; //extend



All synchronization and scheduling required to send the item to the requester is performed by the sequence driver.

The do action is responsible for four tasks:

  1. Waiting for its turn in the sequence driver queue
  2. Generating the data/sequence item using the generation engine (eg. IntelliGen)
  3. Delivering the item to the sequence driver (which delivers it to the BFM)
  4. Waiting for item_done event (usually signaled once the item has been driven into the DUT)

To enable a simplified usage model, one do action that performs so many steps for you automatically is great.  But, as many of you already know - sometimes you need finer control of the scenario. The new sequence API contains several methods, each performing one task of the do:

  1. Waiting for its turn in the sequence driver queue: wait_for_grant() method
  2. Generating the data/sequence item using the generation engine
    1. User can create the item any way they want including gen, new, copy(), etc.
  3. Delivering the item to the sequence driver: deliver_item() method
  4. Waiting for item_done event: wait_for_item_done() method

A simple usage of these methods to send a randomly generated item would be:




gen my_item;




Or, another simple usage example to send an item picked from pre-generated list would be:




my_item = pre_generated_list_of_frames[i].copy();




The obvious advantage of using these methods instead of the do action is that the item can be created procedurally, rather than generated. One case when procedural creation can be useful is when implementing layered protocols. The lower layer creates its data items based on data it pulls from the upper layer.

Let's look at the simplest example, one to one layering.  In this case, the lower layer gets an item from the upper layer, processes it, adds its own data and hands it to its sequence driver.  This means that the lower layer performs two synchronizations - one with the upper layer (when does it have a data item ready for me?) and one with the sequence driver (when is it my turn to send?). The solution most people adopt is using the sequence pre_do() method. The lower layer do-es an item and, in the pre_do(), performs the required changes to the data item, per upper layer status. All this is very nice, but has one problem ... the control flow is complicated and distributed. The user has to extend a method that is automatically called for all do actions of the sequence, its input parameters are predefined, hence if new parameters are required, the user has to define auxiliary fields... not very simple to implement, not simple to debug, and might be difficult to maintain, specially if you have to debug or modify code that had been implemented by someone else - you must examine the code carefully to find all locations in which this sequence is manipulated.

Now, let's see how the new sequence API helps to perform this task in a straight forward manner.

Using the new sequence API, the lower layer sequence can get items from the upper layer and creates its own data items based on the retrieved upper layer item. The item is pulled from upper layer only after a grant has been received, so it is what we call "fresh" - generated based on latest status of the environment. The code might look something like this:




// The get_data_from_upper_layer method would be user

// specific and is not part of the sequence API

upper_layer_s = get_data_from_upper_layer();

my_data = pack(packing.low, upper_layer_s);

gen my_item {keeping .data == my_data};

driver.deliver_item (my_item);



You might be thinking that things are not always that simple. You're right.  For example, what if we are talking many to one layering where the lower layer item is created using several items from the upper layer?  In such cases, the lower layer sequence starts getting items from the upper layer, but suddenly realizes it does not have enough items to  generate a data item of its own. One typical solution is to stall the queue and the lower layer waits until it has enough data.

Using another method of the new API, where there is no need to stall, the lower layer can simply announce "I am not ready yet, try me out next time". This is done using the wait_for_next_grant() method of the new API. This method can be called after the sequence received a grant from the driver, but decides it wants to defer a bit. The driver goes to the next sequence and, after the next item is done, it will return to this sequence.

For such protocols, the lower layer sequence might look something like this:



repeat {

    upper_layer_s = get_data_from_upper_layer();

     if upper_layer_s != NULL then {


     } else {



} until my_data.size == NEEDED_SIZE and    upper_layer_s != NULL

gen my_item {keeping .data == my_data};

driver.deliver_item (my_item);


As you can see, the new API is quite simple and flexible, allowing use models that, until now could be quite complicated to implement.

All these methods (and more) are provided within Specman, starting from the 8.2s2 release. They can be incorporated with the "old" way of using sequences if desired. There is no need to modify any existing code to make use of the new API. The whole verification environment can remain unchanged, while several tests use the API for achieving their specific requirements. As a matter of fact, this is what we do in our own XBus golden example. The sequences implementation remains unchanged, but its examples directory contains now several tests using this API (eg. test_high_performance_no_gen.e).

I have not covered the full functionality of the sequence API in this blog.  For full details on its usage, please read more in the Specman EA document, and see the examples in the OVM e library (ovm_e/examples) which contains several small examples demonstrating the sequences API.  The SOC verification kit (available to all customers on downloads.cadence.com) also contains layering examples. In the OVM e March release (coming soon), the OVM e User Guide will contain detailed descriptions and recommendations of the various use models.


Efrat Shneydor

Sr Member of Consulting Staff 

Solutions Development 

Cadence Design Systems



Leave a Comment

E-mail (will not be published)
 I have read and agree to the Terms of use and Community Guidelines.
Community Guidelines
The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.