quick.gif

space2.gif

space2.gif

space2.gif

space2.gif

space2.gif

space2.gif

space2.gif

   

space.gif

   

space.gif

  ../images/main/bullet_green_ball.gif Variables Inside Methods

To declare a local variable inside a method is same as declaring in a struct, only difference is the variable declaration should start with reserve word var as shown in example below.

   

space.gif

Variables declared inside a method can not be accessed by other methods or outside the method which declares. Thus we call them local variables.

   

space.gif


  1 <'
  2 struct scoreboard { 
  3     // This is global variable
  4      ! mem_list : list of int;
  5     // Just another method
  6     add_item (addr : int) is {
  7       mem_list.push(addr);
  8       // This is local variable
  9       var i : int = 0; // We can assign a default value
 10     };
 11 };
 12 '>
You could download file methods_ex18.e here
   

space.gif

  ../images/main/bullet_green_ball.gif Invoking Methods

Depending on if the method is time consuming method or regular method or we want to make the time consuming method to run as thread we can invoke method as one the way listed below.

   

space.gif

  • tcm()
  • start tcm()
  • method()
  • compute method()
   

space.gif

  ../images/main/bulllet_4dots_orange.gif tcm()

A TCM can be called from another TCM. A called TCM begins execution either when its sampling event occurs or immediately, if the sampling event has already occurred for the current Specman tick.

   

space.gif

The calling TCM waits until the called TCM returns before continuing execution. For this reason, a called TCM is considered a subthread of the calling TCM and shares the same thread handle (thread ID) with the calling TCM.

   

space.gif


  1 <'
  2 struct memory_driver { 
  3     // Define a event for posedge of clock
  4     event pos_clk is rise('top.clk')@sim; 
  5     // Define a method to drive memory write
  6     mem_write( data: byte, addr : byte ) @pos_clk is {
  7       // Wait for one cycle and drive command
  8       wait [1]*cycle;
  9       'top.mem_en'   = 1;
 10       'top.mem_addr' = addr;
 11       'top.mem_data' = data;
 12       'top.mem_wr'   = 1;
 13       outf("Writing to Address %x with Data %x\n",addr,data);
 14       // Wait for one cycle and deassert the command
 15       wait [1]*cycle;
 16       'top.mem_en'   = 0;
 17       'top.mem_addr' = 0;
 18       'top.mem_data' = 0;
 19       'top.mem_wr'   = 0;
 20     }; 
 21    // We use this TCM to call mem_write TCM
 22    mem_tst()@pos_clk is {
 23      mem_write(0x10, 0x5);
 24      mem_write(0x15, 0x6);
 25      mem_write(0xAA, 0x7);
 26      out("Done with Simulation");
 27    };
 28 };
 29 '>
You could download file methods_ex10.e here
   

space.gif

   

space.gif

  ../images/main/bulllet_4dots_orange.gif start tcm()

You can use a start action within another method, either a TCM or a regular method. A started TCM begins execution either when its sampling event occurs or immediately, if the sampling event has already occurred for the current Specman tick.

   

space.gif

A started TCM runs in parallel with the TCM that started it on a separate thread. A started TCM has a unique thread handle (thread ID) that is assigned to it automatically by the scheduler. You can retrieve this handle using one of the predefined methods of the scheduler.

   

space.gif

The recommended way to start an initial TCM, which can then invoke other TCMs, is to extend the related struct's predefined run() method.

   

space.gif

  • A TCM that has a return value cannot be started with a start action.
  • You cannot start a TCM before the run phase begins or after the check phase begins
   

space.gif


  1 <'
  2 // Note : We need a verilog code and Verilog simulator
  3 // to simulate below example
  4 struct memory_driver { 
  5     // Define a event for posedge of clock
  6     event pos_clk is rise('top.clk')@sim; 
  7     // Define a method to drive memory write
  8     mem_write( data: byte, addr : byte ) @pos_clk is {
  9       // Wait for one cycle and drive command
 10       wait [1]*cycle;
 11       'top.mem_en'   = 1;
 12       'top.mem_addr' = addr;
 13       'top.mem_data' = data;
 14       'top.mem_wr'   = 1;
 15       outf("Writing to Address %x with Data %x\n",addr,data);
 16       // Wait for one cycle and deassert the command
 17       wait [1]*cycle;
 18       'top.mem_en'   = 0;
 19       'top.mem_addr' = 0;
 20       'top.mem_data' = 0;
 21       'top.mem_wr'   = 0;
 22     }; 
 23    // We use this TCM to call mem_write TCM
 24    mem_tst()@pos_clk is {
 25      mem_write(0x10, 0x5);
 26      mem_write(0x15, 0x6);
 27      mem_write(0xAA, 0x7);
 28      out("Done with Simulation");
 29    };
 30 };
 31 
 32 extend sys {
 33   memory_driver : memory_driver;
 34   run() is also {
 35     // since the method is tcm use start
 36     // Using start causes TCM run as parallel thread
 37     start memory_driver.mem_tst();
 38   };
 39 };
 40 '>
You could download file methods_ex11.e here
   

space.gif

  ../images/main/bulllet_4dots_orange.gif method()

The proper context for calling a regular method depends on whether the method returns a value or not.

   

space.gif

  • If the method returns a value, it is an expression and can be called from any context where an expression is valid.
  • If the method does not return a value, it is an action and can be called from any context where an action is valid.
   

space.gif


  1 <'
  2 define HIGH 100;
  3 define LOW  50;
  4 struct memory_gen { 
  5      ! err_cnt : int;
  6      ! war_cnt : int;
  7     // Define a event for posedge of clock
  8     event pos_clk is rise('top.clk')@sim; 
  9 
 10     // Define a method to check valid address 
 11     addr_valid(addr : byte ):bool is {
 12       // Check if address is between HIGH and LOW value
 13       // Wait for one cycle and drive command
 14       if ((addr < LOW) || (addr > HIGH)) {
 15         return FALSE;
 16       } else {
 17         return TRUE;
 18       };
 19     }; 
 20 
 21     // This method prints the error and warning count
 22     print_status() is {
 23       outf("Number of Warnings : %d",war_cnt);
 24       outf("Number of Errors   : %d",err_cnt);
 25     };
 26 
 27    // We use this TCM to generate commands,drive them 
 28    // and call out methods 
 29    mem_txgen()@pos_clk is {
 30      var addr : byte; 
 31      // Repeat (NO_COMMANDS)
 32        // generate write/read commands
 33        // Check address
 34        if (addr_valid(addr)) {
 35          // Drive to DUT
 36        } else {
 37          out ("address is not valid, skipping driver");
 38        };
 39      // End repeat
 40      // Call the status method
 41      print_status();
 42      // Stop simulation
 43    };
 44 };
 45 '>
You could download file methods_ex12.e here
   

space.gif

  ../images/main/bulllet_4dots_orange.gif compute method()

In some cases you may want to call a value-returning method without using the value that is returned. To do this, you can use the compute action.


  1 <'
  2 define HIGH 100;
  3 define LOW  50;
  4 define ERR_LIMIT 200;
  5 struct memory_gen { 
  6      ! err_cnt : int;
  7      ! war_cnt : int;
  8     // Define a event for posedge of clock
  9     event pos_clk is rise('top.clk')@sim; 
 10 
 11     // Define a method to check valid address 
 12     addr_valid(addr : byte ):bool is {
 13       // Check if address is between HIGH and LOW value
 14       // Wait for one cycle and drive command
 15       if ((addr < LOW) || (addr > HIGH)) {
 16         return FALSE;
 17       } else {
 18         return TRUE;
 19       };
 20     }; 
 21 
 22     // This method prints the error and warning count
 23     print_status():bool is {
 24       outf("Number of Warnings : %d",war_cnt);
 25       outf("Number of Errors   : %d",err_cnt);
 26       if (err_cnt >= ERR_LIMIT) {
 27         return FALSE;
 28       } else {
 29         return TRUE;
 30       };
 31     };
 32 
 33    // We use this TCM to generate commands,drive them 
 34    // and call out methods 
 35    mem_txgen()@pos_clk is {
 36      var addr : byte; 
 37      // Repeat (NO_COMMANDS)
 38        // generate write/read commands
 39        // Check address
 40        if (addr_valid(addr)) {
 41          // Drive to DUT
 42        } else {
 43          out ("address is not valid, skipping driver");
 44        };
 45      // End repeat
 46      // Call the status method, Since it returns a value
 47      // Which is no use to us, we use 'compute'
 48      compute print_status();
 49      // Stop simulation
 50    };
 51 };
 52 '>
You could download file methods_ex13.e here
   

space.gif

  ../images/main/bulllet_4dots_orange.gif return

Returns immediately from the current method to the method that called it. The execution of the calling method then continues.

   

space.gif

It is not always necessary to provide a return action. When a value returning method ends without a return action, the value of result is returned. Any actions that follow a return action in the method definition are ignored. Actions placed in a method extension are performed before the return is executed.

   

space.gif


  1 <'
  2 define HIGH 100;
  3 define LOW  50;
  4 define ERR_LIMIT 200;
  5 struct memory_gen { 
  6      ! err_cnt : int;
  7      ! war_cnt : int;
  8     // Define a event for posedge of clock
  9     event pos_clk is rise('top.clk')@sim; 
 10 
 11     // Define a method to check valid address 
 12     // This method shows how to use result
 13     addr_valid(addr : byte ):bool is {
 14       // Check if address is between HIGH and LOW value
 15       // Wait for one cycle and drive command
 16       if ((addr < LOW) || (addr > HIGH)) {
 17         result =  FALSE;
 18       } else {
 19         result = TRUE;
 20       };
 21     }; 
 22 
 23     // This method prints the error and warning count
 24     // This method shows how to use return
 25     print_status():bool is {
 26       outf("Number of Warnings : %d",war_cnt);
 27       outf("Number of Errors   : %d",err_cnt);
 28       if (err_cnt >= ERR_LIMIT) {
 29         return FALSE;
 30       } else {
 31         return TRUE;
 32       };
 33     };
 34 
 35     // This method shows how to use return without a value
 36     print_parity(data:byte, addr:byte) is {
 37       if (addr_valid(addr)) {
 38         var parity : bit = data[7:7]^data[6:6]^data[5:5]^
 39                            data[4:4]^data[3:3]^data[2:2]^
 40                            data[1:1]^data[0:0];
 41         outf ("Parity of data is %b\n", parity);
 42       } else {
 43         return;
 44         // This will not be executed
 45         outf ("Address is not valid");
 46       };
 47     };
 48 
 49    // We use this TCM to generate commands,drive them 
 50    // and call out methods 
 51    mem_txgen()@pos_clk is {
 52      var addr : byte; 
 53      // Repeat (NO_COMMANDS)
 54        // generate write/read commands
 55        // Check address
 56        if (addr_valid(addr)) {
 57          // Drive to DUT
 58        } else {
 59          out ("address is not valid, skipping driver");
 60        };
 61      // End repeat
 62      // Call the status method, Since it returns a value
 63      // Which is no use to us, we use 'compute'
 64      compute print_status();
 65      // Stop simulation
 66    };
 67 };
 68 '>
You could download file methods_ex14.e here
   

space.gif

   

space.gif

   

space.gif

   

space.gif

space2.gif

space2.gif

space2.gif

space2.gif

space2.gif

  

Copyright © 1998-2014

Deepak Kumar Tala - All rights reserved

Do you have any Comment? mail me at:deepak@asic-world.com