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
 
   task body();
      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
   endtask: body
 
   `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
 
   task main_phase( uvm_phase phase );
      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 ) );
   endtask: main_phase
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 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页