VMM SCENARIO GENERATOR

Atomic generator generates individual data items or transaction descriptors. Each item is generated independently of other items in a random fashion. Atomic generator is simple to describe and use.

Unlike atomic generator, a scenario generator generates a sequence of transaction.

  Example of sequence of transaction: 

CPU instructions like LOAD__A,LOAD__B,ADD_A_B,STORE_C. 
Packets with incrementing length.
Do write operation to address "123" and then do the read to address "123".
 
It is very unlikely that atomic generator to generate transaction in the above ordered sequence. With scenario generator, we can generate these sequence of transaction.

VMM provides `vmm_scenario_gen() macro for quickly creating a scenario generator.

`vmm_scenario_gen (class_name , "Class Description" );

The macro defines classes named <class_name>_scenario_gen, <class_name>_scenario, <class_name>_scenario_election , <class_name>_scenario_gen_callbacks and <class_name>_atomic_scenario.

    class custom_scenario_gen extends vmm_xactor ;
    class custom_scenario extends vmm_data ;
    class custom_atomic_scenario extends custom_scenario ;
    class custom_scenario_election ;
    class custom_scenario_gen_callbacks extends vmm_xactor_callbacks

  <class_name>_scenario:

This scenario generator can generate more than one scenario. Each scenario which can contain more than one transaction is described in a class which is extended from <class_name>_scenario.

For each scenario, following variables must be constraint.
 Length: number of transactions in an array.
 Repeated: number of times to repeat this scenario.

  <class_name>_atomic_scenario:

This class is a atomic scenario. This is the default scenario. This scenario is a random transactions.

  <class_name>_scenario_election:

This class is the arbiter which determines the order that the known scenarios are applied. By default, scenarios are elected atomically. User can extend this class to define an order in which the scenarios should be picked.

  <class_name>_scenario_gen:

This class is the scenario generator which generates the transactions and sends out using output channel. This class has a queue of scenario objects. Each scenario contains transaction instances in an array. 

  <class_name>_scenario_gen_callbacks:

This class provides callback mechanism. There are two callback methods define. pre_scenario_randomize() and post_scenario_gen() which are called at pre-randomization of the scenario and post-generation of the scenario respectively. 




  Example 

Let us write an example.

Following is the transaction class which we will use to write a scenario generator.


class instruction extends vmm_data ;
   vmm_log log ;
   typedef enum { LOAD__A , LOAD__B , ADD_A_B , SUB_A_B , STORE_C } kinds_e ;
   rand kinds_e inst ;

   function new ();
      super . new ( this .log );
   endfunction : new

   virtual function string psdisplay ( string prefix = "" );
         psdisplay =  $psprintf ( "  Instruction : %s | stream_id : %0d | scenario_id : %0d " ,inst . name (),stream_id ,scenario_id );
   endfunction :psdisplay

   virtual function vmm_data allocate ();
      instruction tr = new ;
      allocate = tr ;
   endfunction :allocate

   virtual function vmm_data copy (vmm_data cpy = null );
      instruction to ;
      if (cpy == null )
         to = new ;
       else
         if (! $cast (to , cpy )) begin
            `vmm_fatal ( this .log , "Attempting to copy to a non instruction instance" );
            return null ;
        end
      super .copy_data (to );
      to .inst = this .inst ;
      copy = to ;
   endfunction :copy
endclass

 

The above transaction crests CPU instructions.

Let us consider that sequence of instruction LOAD__A,LOAD__B,ADD_A_B,STORE_C  is a interesting scenario and LOAD__A,LOAD__B,SUB_A_B,STORE_C is also an interesting scenario.
When instructions are generated, we want to generate these 2 sequences of instruction. Let us see how to generate these 2 sequence of instructions .

As we have already discussed, `vmm_scenario_gen() creates use full class for cscenario generation.

1) Use  `vmm_scenario_gen() macro to declare the scenario classes.

`vmm_scenario_gen (instruction , "Instruction Scenario Generator" )

   This macro will create following classs

    instruction_scenario_gen
    instruction_scenario
    instruction_atomic_scenario
    instruction_scenario_election
    instruction_scenario_gen_callbacks

2) Define interesting scenarios by extending inst_scenario;

class instruction_scenario_add_sub extends instruction_scenario ;

3) Define the first scenario. It is sequence of instructions for addition operation.

   a) Declare a variable for identifying the scenario.

          int addition_scenario_id  ;

   Each scenario has more than one inductions. All these instructions are in a queue "items"   which is already defined in    "instruction_scenario".

   The rand varible "scenario_kind", which pre defined in the vmm_scenario class, will randomly select one of the defined scenarios. "scenario_kind" varible has the id of the current scenario. So we have to define the addition scenario, when the "scenario_kind" value is addition_scenario_id.

   b) Constrain the scenario kind, 

      constraint addition_scenario_items {
                if ( $void (scenario_kind ) == addition_scenario_id ) {

   c)  The number of instructions define in a scenario is specified by the predefined variable "length". In our example, we have 4 instructions. So constrain the length to 4.

        length == 4 ;

   d) The predefined variable "repeated" used to control if the VMM scenario generator would run the scenario more than once each time it is created. We are not interested in repeating so, constrain it to 0

        repeated == 0 ;

   e) Constrain the individual items based on the requirements if this scenario is selected. Our requirement in this example is that "inst" should follow the sequence LOAD__A,LOAD__B,ADD_A_B,STORE_C

   foreach (items [i ])
        if (i == 0 )
           this .items [i ].inst == instruction :: LOAD__A ;
        else if (i == 1 )
           this .items [i ].inst == instruction :: LOAD__B ;
        else if (i == 2 )
           this .items [i ].inst == instruction :: ADD_A_B ;
        else if (i == 3 )
           this .items [i ].inst == instruction :: STORE_C ;


4)Define second scenario. It is Sequence of instructions for subtraction operation.    


   a) Declare a variable for identifying the scenario.

      int subtraction_scenario_id ;

   b) Constrain the scenario kind, 

      constraint subtraction_scenario_items {
              if ( $void (scenario_kind ) == subtraction_scenario_id ) {

   c) Constrain the length

      length == 4 ;

   d) Constrain the repeated

      repeated == 0 ;

   e) Constrain the items

     foreach (items [i ])
        if (i == 0 )
           this .items [i ].inst == instruction :: LOAD__A ;
        else if (i == 1 )
           this .items [i ].inst == instruction :: LOAD__B ;
        else if (i == 2 )
           this .items [i ].inst == instruction :: SUB_A_B ;
        else if (i == 3 )
           this .items [i ].inst == instruction :: STORE_C ;

5)Define constructor method.
  
   a) call the super.new() method.
   
      Get a unique Ids from the define_scenario() method for each scenario.
      define_scenario() is predefined in  *_scenario class. 

         function new ();
             this .addition_scenario_id = define_scenario ( " ADDITION " , 4 );
             this .subtraction_scenario_id = define_scenario ( " SUBSTRACTION " , 4 );
         endfunction


  With this, we completed the implementation of scenarios.

  Scenario Code 

`vmm_scenario_gen (instruction , "Instruction Scenario Generator" )

class instruction_scenario_add_sub extends instruction_scenario ;

///
//              ADDITION SCENARIO                //
///

  int addition_scenario_id  ;

  constraint addition_scenario_items {
       if ( $void (scenario_kind ) == addition_scenario_id ) {
        repeated == 0 ;
        length == 4 ;
        foreach (items [i ])
        if (i == 0 )
           this .items [i ].inst == instruction :: LOAD__A ;
        else if (i == 1 )
           this .items [i ].inst == instruction :: LOAD__B ;
        else if (i == 2 )
           this .items [i ].inst == instruction :: ADD_A_B ;
        else if (i == 3 )
           this .items [i ].inst == instruction :: STORE_C ;
       }
  }

///
//            ASUBTRACTION SCENARIO              //
///

  int subtraction_scenario_id ;

  constraint subtraction_scenario_items {
       if ( $void (scenario_kind ) == subtraction_scenario_id ) {
        repeated == 0 ;
        length == 4 ;
        foreach (items [i ])
        if (i == 0 )
           this .items [i ].inst == instruction :: LOAD__A ;
        else if (i == 1 )
           this .items [i ].inst == instruction :: LOAD__B ;
        else if (i == 2 )
           this .items [i ].inst == instruction :: SUB_A_B ;
        else if (i == 3 )
           this .items [i ].inst == instruction :: STORE_C ;
       }
   }

   function new ();
       this .addition_scenario_id = define_scenario ( " ADDITION " , 4 );
       this .subtraction_scenario_id = define_scenario ( " SUBSTRACTION " , 4 );
   endfunction

endclass

  Testcase 

  Now we will write a test case to see how to above defined scenario works.

1) Declare scenario generator

     instruction_scenario_gen gen ;

2) Declare the scenario which we defined earlier.

     instruction_scenario_add_sub sce_add_sub ;

3) Construct the generator and scenarios.

     gen = new ( "gen" , 0 );
     sce_add_sub = new ();

4) set the number of instances and scenarios generated by generator to 20 and 4 respectevy.

     gen .stop_after_n_insts = 20 ;
     gen .stop_after_n_scenarios = 4 ;

5) Scenario generators store all the scenarios in scenario_set queue. So, we have to add the scenario which we constructed above to the queue.

     gen .scenario_set [ 0 ] = sce_add_sub ;

6) Start the generator

     gen .start_xactor ();

7) Similar t the Atomic generator, the transactions  created by the scenario generator are sent to out_chan channel.
   Get the instructions from the out_chan channel and print the content.

     repeat ( 20 ) begin
     gen .out_chan . get (inst );
     inst .display ();

   Testcase code

program test ();

     instruction_scenario_gen gen ;
     instruction_scenario_add_sub sce_add_sub ;
     instruction inst ;

     initial
     begin
         gen = new ( "gen" , 0 );
         sce_add_sub = new ();

         //gen.log.set_verbosity(vmm_log::DEBUG_SEV,"/./","/./");
         gen .stop_after_n_insts = 20 ;
         gen .stop_after_n_scenarios = 4 ;

         gen .scenario_set [ 0 ] = sce_add_sub ;

         gen .start_xactor ();

         repeat ( 20 ) begin
         gen .out_chan . get (inst );
         inst .display ();
         end

     end

endprogram

  Down load the source code

vmm_scenario.tar
Browse the code in vmm_scenario.tar

  Command to simulate
vcs -sverilog -ntb_opts rvm -f filelist -R

Observe the log file , you can see the both the scenarios .

  Logfile

  Instruction : LOAD__A | stream_id : 0 | scenario_id : 0
  Instruction : LOAD__B | stream_id : 0 | scenario_id : 0
  Instruction : ADD_A_B | stream_id : 0 | scenario_id : 0
  Instruction : STORE_C | stream_id : 0 | scenario_id : 0

  Instruction : LOAD__A | stream_id : 0 | scenario_id : 1
  Instruction : LOAD__B | stream_id : 0 | scenario_id : 1
  Instruction : ADD_A_B | stream_id : 0 | scenario_id : 1
  Instruction : STORE_C | stream_id : 0 | scenario_id : 1

  Instruction : LOAD__A | stream_id : 0 | scenario_id : 2
  Instruction : LOAD__B | stream_id : 0 | scenario_id : 2
  Instruction : SUB_A_B | stream_id : 0 | scenario_id : 2
  Instruction : STORE_C | stream_id : 0 | scenario_id : 2

  Instruction : LOAD__A | stream_id : 0 | scenario_id : 3
  Instruction : LOAD__B | stream_id : 0 | scenario_id : 3
  Instruction : ADD_A_B | stream_id : 0 | scenario_id : 3
  Instruction : STORE_C | stream_id : 0 | scenario_id : 3

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值