UVM Tutorial for Candy Lovers – 7. Virtual Sequence

Did you know the mix of two lemon and two coconut jelly beans will create the flavor of lemon meringue pie? And the mix of two strawberry and two vanilla jelly beans will create the flavor of strawberry shortcake? This post will provide an explanation on the virtual sequence to create these new jelly-bean recipes.

Overview

The first figure shows the relationship of the verification components used in this post. The jelly_bean_taster (DUT) from the previous posts was “enhanced” to take two jelly-bean flavors at the same time through two jelly_bean_ifs. This new DUT is referred to as the jelly_bean_taster_subsystem. To drive the two interfaces, two instances of jelly_bean_agent are used. The jelly_bean_recipe_virtual_sequence orchestrates the creation of jelly-bean flavors in order to make a new flavor. The second figure at the bottom of the page shows the verification components in a class diagram, and the third figure shows the verification objects in a class diagram.

Verification Platform

Virtual Sequence

The virtual sequence defines three new jelly-bean recipes (LEMON_MERINGUE_PIESTRAWBERRY_SHORTCAKE, and CANDY_APPLE) on the second line. Each recipe requires two jelly-bean flavors. For example, to create the LEMON_MERINGUE_PIE recipe, two LEMON jelly beans and two COCONUT jelly beans are necessary. Two sub-sequences (same_flavored_jelly_beans_sequence) are created (line 19) to generate two flavors. The case statement on the line 21 prepares two jelly-bean flavors based on the recipe. At the end of the body task, the two sub-sequences are started in parallel (line 42).

class jelly_bean_recipe_virtual_sequence extends uvm_sequence#( uvm_sequence_item );
typedef enum bit[1:0] { LEMON_MERINGUE_PIE,   // 2 LEMON      + 2 COCONUT
STRAWBERRY_SHORTCAKE, // 2 STRAWBERRY + 2 VANILLA
CANDY_APPLE           // 2 APPLE      + 1 CINNAMON
} recipe_e;
rand recipe_e recipe;

jelly_bean_sequencer jb_seqr1;
jelly_bean_sequencer jb_seqr2;

same_flavored_jelly_beans_sequence jb_seq1;
same_flavored_jelly_beans_sequence jb_seq2;

function new( string name = "" );
super.new( name );
endfunction: new

jb_seq1 = same_flavored_jelly_beans_sequence::type_id::create( .name( "jb_seq1" ), .contxt( get_full_name() ) );
jb_seq2 = same_flavored_jelly_beans_sequence::type_id::create( .name( "jb_seq2" ), .contxt( get_full_name() ) );
case ( recipe )
LEMON_MERINGUE_PIE: begin
jb_seq1.flavor          = jelly_bean_transaction::LEMON;
jb_seq2.flavor          = jelly_bean_transaction::COCONUT;
jb_seq1.num_jelly_beans = 2;
jb_seq2.num_jelly_beans = 2;
end
STRAWBERRY_SHORTCAKE: begin
jb_seq1.flavor          = jelly_bean_transaction::STRAWBERRY;
jb_seq2.flavor          = jelly_bean_transaction::VANILLA;
jb_seq1.num_jelly_beans = 2;
jb_seq2.num_jelly_beans = 2;
end
CANDY_APPLE: begin
jb_seq1.flavor          = jelly_bean_transaction::APPLE;
jb_seq2.flavor          = jelly_bean_transaction::CINNAMON;
jb_seq1.num_jelly_beans = 2;
jb_seq2.num_jelly_beans = 1;
end
endcase // case ( recipe )
uvm_info( get_name(), { "\n", this.sprint() }, UVM_LOW )
fork
jb_seq1.start( .sequencer( jb_seqr1 ), .parent_sequence( this ) );
jb_seq2.start( .sequencer( jb_seqr2 ), .parent_sequence( this ) );
join

uvm_object_utils_begin( jelly_bean_recipe_virtual_sequence )
uvm_field_enum  ( recipe_e, recipe, UVM_ALL_ON )
uvm_field_object( jb_seq1,          UVM_ALL_ON )
uvm_field_object( jb_seq2,          UVM_ALL_ON )
uvm_object_utils_end
endclass: jelly_bean_recipe_virtual_sequence

Test

The jelly_bean_recipe_test class creates the above mentioned virtual sequence. Firstly, the test assigns two jelly_bean_sequencers to the virtual sequence (line 13 and 14). By doing this, the sub-sequence, jb_seq1, will run on the sequencer in the agent #1, and the sub-sequence, jb_seq2, will run on the sequencer in the agent #2. The test randomizes the virtual sequence and starts the sequence on the line 15 and 16. Note that the sequencer argument of the start task takes null since there is no sequencer associated with the virtual sequence.

class jelly_bean_recipe_test extends jelly_bean_base_test;
uvm_component_utils( jelly_bean_recipe_test )

function new( string name, uvm_component parent );
super.new( name, parent );
endfunction: new

jelly_bean_recipe_virtual_sequence jb_vseq;

phase.raise_objection( .obj( this ) );
jb_vseq = jelly_bean_recipe_virtual_sequence::type_id::create( .name( "jb_vseq" ), .contxt( get_full_name() ) );
jb_vseq.jb_seqr1 = jb_env.jb_agent1.jb_seqr;
jb_vseq.jb_seqr2 = jb_env.jb_agent2.jb_seqr;
assert( jb_vseq.randomize() );
jb_vseq.start( .sequencer( null ) );
#100ns ;
phase.drop_objection( .obj( this ) );
endclass: jelly_bean_recipe_test

Simulation

Let’s run a simulation to see what flavors the virtual sequence generates. In my case, the sequence generated a CANDY_APPLE recipe. It in turn made the first sequence (jb_seq1) generate two APPLE jelly beans, and made the second sequence (jb_seq2) generate one CINNAMON jelly bean.

UVM_INFO jb.sv(266) @ 0: reporter@@jb_vseq [jb_vseq]
------------------------------------------------------------------------------------
Name                           Type                                Size  Value
------------------------------------------------------------------------------------
jb_vseq                        jelly_bean_recipe_virtual_sequence  -     @1196
recipe                       recipe_e                            2     CANDY_APPLE
jb_seq1                      same_flavored_jelly_beans_sequence  -     @1200
num_jelly_beans            integral                            32    'h2
flavor                     jelly_bean_transaction::flavor_e    3     APPLE
req                        object                              -
rsp                        object                              -
jb_seq2                      same_flavored_jelly_beans_sequence  -     @1204
num_jelly_beans            integral                            32    'h1
flavor                     jelly_bean_transaction::flavor_e    3     CINNAMON
req                        object                              -
rsp                        object                              -
depth                        int                                 32    'd1
parent sequence (name)       string                              0     ""
parent sequence (full name)  string                              0     ""
sequencer                    string                              0     ""
req                          object                              -
rsp                          object                              -
------------------------------------------------------------------------------------`

I hope this tutorial helped you understand the virtual sequence. Oh, for those of you who are interested in more jelly-bean recipes, consult this site

03-30 580