VMM CALLBACK

Callback mechanism is used for altering the behavior of the transactor without modifying the transactor. One of the many promises of Object-Oriented programming is that it will allow for plug-and-play re-usable verification components. Verification Designers will hook the transactors together to make a verification environment. In SystemVerilog, this hooking together of transactors can be tricky. Callbacks provide a mechanism whereby independently developed objects may be connected together in simple steps.

This article describes vmm callbacks. Vmm callback might be used for simple notification, two-way communication, or to distribute work in a process. Some requirements are often unpredictable when the transactor is first written. So a transactor should provide some kind of hooks for executing the code which is defined afterwards. In vmm, these hooks are created using callback methods. For instance, a driver is developed and an empty method is called before driving the transaction to the DUT. Initially this empty method does nothing. As the implementation goes, user may realize that he needs to print the state of the transaction or to delay the transaction driving to DUT or inject an error into transaction. Callback mechanism allows executing the user defined code in place of the empty callback method.  Other example of callback usage is in monitor. Callbacks can be used in a monitor for collecting coverage information or for hooking up to scoreboard to pass transactions for self checking. With this, user is able to control the behavior of the transactor in verification environment and individual testcases without doing any modifications to the transactor itself. 

Following are the steps to be followed to create a transactor with callbacks. We will see simple example of creating a Driver transactor to support callback mechanism.

1) Define a facade class.
   Extend the vmm_xactor_callbacks class to create a faced class.
   Define required callback methods. All the callback methods must be virtual.
   In this example, we will create callback methods which will be called before driving the packet and after driving the packet to DUT.

class Driver_callbacks extends vmm_xactor_callbacks ;

  virtual task pre_send (); endtask
  virtual task post_send (); endtask

endclass

2) Calling callback method.
   Inside the transactor, callback methods should be called whenever something interesting happens.
   We will call the callback method before driving the packet and after driving the packet. We defined 2 methods in facade class. We will call pre_send() method before sending the packet and post_send() method after sending the packet.

   Using a `vmm_callback(,) macro, callback methods are called.
   There are 2 argumentd to `vmm_callback(,) macro.
   First argument must be the facade class.
   Second argument must be the callback method in the facade class.

   To call pre_send() method , use macro
   `vmm_callback(Driver_callbacks,pre_send());
   and simillary to call post_send() method,
   `vmm_callback(Driver_callbacks,post_send());

   Place the above macros before and after driving the packet.


    virtual task main ();
   super .main ();
   
     forever begin
        `vmm_callback (Driver_callbacks ,pre_send ());
         $display ( " Driver: Started Driving the packet ...... %d" , $time ); 
         // Logic to drive the packet goes hear
         // let's consider that it takes 40 time units to drive a packet.
         # 40 ;
         $display ( " Driver: Finished Driving the packet ...... %d" , $time );  
        `vmm_callback (Driver_callbacks ,post_send ());
     end
   endtask


   With this, the Driver implementation is completed with callback support.


   Complete Source Code 
  
class Driver_callbacks extends vmm_xactor_callbacks ;

  virtual task pre_send (); endtask
  virtual task post_send (); endtask

endclass


class Driver extends vmm_xactor ;

function new ();
   super . new ( "Driver" , "class" );
endfunction

virtual task main ();
   super .main ();
   
     forever begin
        `vmm_callback (Driver_callbacks ,pre_send ());
         $display ( " Driver: Started Driving the packet ...... %d" , $time ); 
         // Logic to drive the packet goes hear
         // let's consider that it takes 40 time units to drive a packet.
         # 40 ;
         $display ( " Driver: Finished Driving the packet ...... %d" , $time );  
        `vmm_callback (Driver_callbacks ,post_send ());
     end
  endtask

endclass


Let's run the driver in simple testcase. In this testcase, we are not changing any callback methods definitions.

   Testcase 1 Source Code 

program testing_callbacks ();
   Driver drvr =  new ();
  initial
    begin
    # 100 drvr .start_xactor ();
    # 200 drvr .stop_xactor ();
    end
  endprogram

   Download files

vmm_callback.tar
Browse the code in vmm_callback.tar

   Command to run the simulation
vcs -sverilog -f filelist -R -ntb_opts rvm -ntb_opts dtm

   Log report

Driver: Started Driving the packet ......                  100
Driver: Finished Driving the packet ......                  140
Driver: Started Driving the packet ......                  140
Driver: Finished Driving the packet ......                  180
Driver: Started Driving the packet ......                  180
Driver: Finished Driving the packet ......                  220
Driver: Started Driving the packet ......                  220
Driver: Finished Driving the packet ......                  260
Driver: Started Driving the packet ......                  260
Driver: Finished Driving the packet ......                  300
Driver: Started Driving the packet ......                  300
$finish at simulation time                  300


Following steps are to be performed for using callback mechanism to do required functionality.
We will see how to use the callbacks which are implemented in the above defined driver in a testcase.

1) Implement the user defined callback method by extending facade class of the driver class.
   We will delay the driving of packet be 20 time units using the pre_send() call back method.
   We will just print a message from post_send() callback method.

     class Custom_Driver_callbacks_1 extends Driver_callbacks ;
  
     virtual task pre_send ();
       $display ( "CB_1:pre_send: Delaying the packet driving by 20 time units. %d" , $time );
       # 20 ;
     endtask
 
     virtual task post_send ();
      $display ( "CB_1:post_send: Just a message from  post send callback method \n" );
     endtask


2) Construct the user defined facade class object.

     Custom_Driver_callbacks CDc = new ();

3) Register the callback method. vmm_xactor class has append_callback() which is used to register the callback.


   drvr .append_callback (CDc_1 );

   Testcase 2 Source Code 

   program testing_callbacks ();
   Driver drvr =  new ();

   class Custom_Driver_callbacks_1 extends Driver_callbacks ;
  
     virtual task pre_send ();
       $display ( "CB_1:pre_send: Delaying the packet driving by 20 time units. %d" , $time );
       # 20 ;
     endtask
 
     virtual task post_send ();
      $display ( "CB_1:post_send: Just a message from  post send callback method \n" );
     endtask

   endclass

   Custom_Driver_callbacks_1 CDc_1 = new ();
  initial
    begin
    drvr .append_callback (CDc_1 );
    # 100 drvr .start_xactor ();
    # 200 drvr .stop_xactor ();
    end
  endprogram

   Download the example

vmm_callback_1.tar
Browse the code in vmm_callback_1.tar

   Simulation Command
vcs -sverilog -f filelist -R -ntb_opts rvm -ntb_opts dtm


  Run the testcase. See the log results; We delayed the driving of packet by 20 time units using callback mechanism. See the difference between the previous testcase log and this log.

   Log report

CB_1:pre_send: Delaying the packet driving by 20 time units.                  100
Driver: Started Driving the packet ......                  120
Driver: Finished Driving the packet ......                  160
CB_1:post_send: Just a message from  post send callback method

CB_1:pre_send: Delaying the packet driving by 20 time units.                  160
Driver: Started Driving the packet ......                  180
Driver: Finished Driving the packet ......                  220
CB_1:post_send: Just a message from  post send callback method

CB_1:pre_send: Delaying the packet driving by 20 time units.                  220
Driver: Started Driving the packet ......                  240
Driver: Finished Driving the packet ......                  280
CB_1:post_send: Just a message from  post send callback method

CB_1:pre_send: Delaying the packet driving by 20 time units.                  280
Driver: Started Driving the packet ......                  300
$finish at simulation time                  300

  


Now we will see registering 2 callback methods.
   1) Define another user defined callback methods by extending facade class.

     class Custom_Driver_callbacks_2 extends Driver_callbacks ;
  
     virtual task pre_send ();
       $display ( "CB_2:pre_send: Hai .... this is from Second callback %d" , $time );
     endtask
 
    endclass

   2) Construct the user defined facade class object.

      Custom_Driver_callbacks_2 CDc_2 = new ();

   3) Register the object

      drvr .append_callback (CDc_2 );

   Testcase 3 Source Code  
   
  program testing_callbacks ();
   Driver drvr =  new ();

   class Custom_Driver_callbacks_1 extends Driver_callbacks ;
  
     virtual task pre_send ();
       $display ( "CB_1:pre_send: Delaying the packet driving by 20 time units. %d" , $time );
       # 20 ;
     endtask
 
     virtual task post_send ();
      $display ( "CB_1:post_send: Just a message from  post send callback method \n" );
     endtask

   endclass

   class Custom_Driver_callbacks_2 extends Driver_callbacks ;
  
     virtual task pre_send ();
       $display ( "CB_2:pre_send: Hai .... this is from Second callback %d" , $time );
     endtask
 

   endclass

   Custom_Driver_callbacks_1 CDc_1 = new ();
   Custom_Driver_callbacks_2 CDc_2 = new ();
  initial
    begin
    drvr .append_callback (CDc_1 );
    drvr .append_callback (CDc_2 );
    # 100 drvr .start_xactor ();
    # 200 drvr .stop_xactor ();
    end
  endprogram

   Download source code

vmm_callback_2.tar
Browse the code in vmm_callback_2.tar

   Command to run the simulation
vcs -sverilog -f filelist -R -ntb_opts rvm -ntb_opts dtm


Run the testcase and analyze the result.

   Log report

CB_1:pre_send: Delaying the packet driving by 20 time units.                  100
CB_2:pre_send: Hai .... this is from Second callback                  120
Driver: Started Driving the packet ......                  120
Driver: Finished Driving the packet ......                  160
CB_1:post_send: Just a message from  post send callback method

CB_1:pre_send: Delaying the packet driving by 20 time units.                  160
CB_2:pre_send: Hai .... this is from Second callback                  180
Driver: Started Driving the packet ......                  180
Driver: Finished Driving the packet ......                  220
CB_1:post_send: Just a message from  post send callback method

CB_1:pre_send: Delaying the packet driving by 20 time units.                  220
CB_2:pre_send: Hai .... this is from Second callback                  240
Driver: Started Driving the packet ......                  240
Driver: Finished Driving the packet ......                  280
CB_1:post_send: Just a message from  post send callback method

CB_1:pre_send: Delaying the packet driving by 20 time units.                  280
CB_2:pre_send: Hai .... this is from Second callback                  300
Driver: Started Driving the packet ......                  300
$finish at simulation time                  300



The log results show that pre_send() method of CDc_1 is called first and then pre_send() method of Cdc_2. This is beacuse of the order of the registering callbacks.

    drvr .append_callback (CDc_1 );
    drvr .append_callback (CDc_2 );


Now we will see how to change the order of the callback method calls.
Use prepend_callback() method for registering instead of append_callback() method.

   Testcase 4 Source Code 

program testing_callbacks ();
   Driver drvr =  new ();

   class Custom_Driver_callbacks_1 extends Driver_callbacks ;
  
     virtual task pre_send ();
       $display ( "CB_1:pre_send: Delaying the packet driving by 20 time units. %d" , $time );
       # 20 ;
     endtask
 
     virtual task post_send ();
      $display ( "CB_1:post_send: Just a message from  post send callback method \n" );
     endtask

   endclass

   class Custom_Driver_callbacks_2 extends Driver_callbacks ;
  
     virtual task pre_send ();
       $display ( "CB_2:pre_send: Hai .... this is from Second callback %d" , $time );
     endtask
 

   endclass

   Custom_Driver_callbacks_1 CDc_1 = new ();
   Custom_Driver_callbacks_2 CDc_2 = new ();
  initial
    begin
    drvr .append_callback (CDc_1 );
    drvr .prepend_callback (CDc_2 );
    # 100 drvr .start_xactor ();
    # 200 drvr .stop_xactor ();
    end
  endprogram

   Download the source code

vmm_callback_3.tar
Browse the code in vmm_callback_3.tar

   Command to run the simulation
vcs -sverilog -f filelist -R -ntb_opts rvm -ntb_opts dtm


Run and analyze the results.
Log results show that, pre_send() method of CDs_1 is called after calling CDs_2 pre_send() method.

   Log file report

CB_2:pre_send: Hai .... this is from Second callback                  100
CB_1:pre_send: Delaying the packet driving by 20 time units.                  100
Driver: Started Driving the packet ......                  120
Driver: Finished Driving the packet ......                  160
CB_1:post_send: Just a message from  post send callback method

CB_2:pre_send: Hai .... this is from Second callback                  160
CB_1:pre_send: Delaying the packet driving by 20 time units.                  160
Driver: Started Driving the packet ......                  180
Driver: Finished Driving the packet ......                  220
CB_1:post_send: Just a message from  post send callback method

CB_2:pre_send: Hai .... this is from Second callback                  220
CB_1:pre_send: Delaying the packet driving by 20 time units.                  220
Driver: Started Driving the packet ......                  240
Driver: Finished Driving the packet ......                  280
CB_1:post_send: Just a message from  post send callback method

CB_2:pre_send: Hai .... this is from Second callback                  280
CB_1:pre_send: Delaying the packet driving by 20 time units.                  280
Driver: Started Driving the packet ......                  300
$finish at simulation time                  300



Vmm also provides method to remove the callback methods which are registered .



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值