Tuesday, September 29, 2015

Static and Automatic Lifetime of Variable and Methods

Static : For a variable static lifetime is , its memory never de-allocated until simulation ends.
Automatic : For a variable Automatic lifetime is , it is stack storage of variable (for multiple entry to a task, function or block, it will have stack storage) and its memory will be de-allocated once execution of that method or block is over.

Default Lifetime of variable :

1. Class variable : Automatic
2. Method variable : Automatic
3. Local variable of loop : Automatic
4. Module or Program block variable : Static
5. Variable declared in initial of always block : Static

I am explaining default lifetime of all above category.

Class Variable : Default all variable and class method are automatic. Each instance of class will have its own copy of variable. If it is declared as static only one copy will be created and all instance will use that copy. Static variable can be accessed with out creating object of class. It can be accessed with out making object and by scope resolution operation.

Method Variable : Default lifetime of variable declared in method (Function and Task) is automatic. Scope of the variable is limited to execution of that method.
Its lifetime is automatic as its memory will be deallocated when the task and function gets over.

Loop Variable : Default local variable of loop is automatic. Its scope is limited to execution of call and its memory deallocated when execution of loop is over.

Module or Program Block : Default lifetime of variable is Static for Module and Program. They will have memory till end of simulation and its scope will be limited to that module or program called.


Default lifetime of Method :

1. Method in module or program block : Static
2. Method in class : Automatic

Method in module and program block : Default life time of method in program and module block is static. This is to keep it same with existing verilog reference. So for module function lifetime is static. Its variable and return type is static. So if we call recursive function, it will not create multiple stack entry for call of function and stack memory for internal variable.

See below program.

In below program factorial function is recursive. But as default it is static it will not create stack entry for it.
module tryfact;
  // define the function
  function  integer factorial (input [31:0] operand);
  begin
    if (operand >= 2)
    factorial = factorial (operand - 1) * operand;
    else
    factorial = 1;
  end
  endfunction: factorial
  // test the function
  integer result;
  initial begin
    for (int n = 0; n <= 7; n++) begin
      result = factorial(n);
      $display("%0d factorial=%0d", n, result);
    end
  end
endmodule: tryfact

Output :
0 factorial=1
1 factorial=1
2 factorial=1
3 factorial=1
4 factorial=1
5 factorial=1
6 factorial=1
7 factorial=1

See below function is automatic.
module tryfact;
  // define the function
  function automatic integer factorial (input [31:0] operand);
  begin
    if (operand >= 2)
    factorial = factorial (operand - 1) * operand;
    else
    factorial = 1;
  end
  endfunction: factorial
  // test the function
  integer result;
  initial begin
    for (int n = 0; n <= 7; n++) begin
      result = factorial(n);
      $display("%0d factorial=%0d", n, result);
    end
  end
endmodule: tryfact

Output : 
0 factorial=1
1 factorial=1
2 factorial=2
3 factorial=6
4 factorial=24
5 factorial=120
6 factorial=720
7 factorial=5040

Below function get is static by default. So its value is incremented in every call
module test();
  function get;
    int i;
    i++;
    $display(i);
  endfunction
  initial begin
    repeat(10) begin
      get();
    end
  end
endmodule

Output :
1
2
3
4
5
6
7
8
9
10


Method in Class : Method in class have default lifetime Automatic. It will create multiple call entry and variable(related to method) memory entry. See below code.

class tryfact;
  // define the function
  function integer factorial (input [31:0] operand);
    if (operand >= 2)
    factorial = factorial (operand - 1) * operand;
    else
    factorial = 1;
  endfunction: factorial
endclass

module top();
  // test the function
  tryfact tf;
  integer result;
  initial begin
    tf = new();
    for (int n = 0; n <= 7; n++) begin
      result = tf.factorial(n);
      $display("%0d factorial=%0d", n, result);
    end
  end 
endmodule: top

Output :
0 factorial=1
1 factorial=1
2 factorial=2
3 factorial=6
4 factorial=24
5 factorial=120
6 factorial=720
7 factorial=5040

Below function get and its variable i is automatic by default. So it will not increment with every call.
class base;
  function get;
    int i;
    i++;
    $display(i);
  endfunction
endclass

module test();
  initial begin
    base b1,b2;
    b1 = new();
    b2 = new();
    repeat(10) begin
      b1.get();
    end
    $display("@@@@");
    b2.get();
  end
endmodule

Output : 
1
1
1
1
1
1
1
1
1
1
@@@@
1

class base;
  function static get;
    int i; // function static or static int i ,will have same result
    i++;   // Since function static indeed set lifetime for its local variable
    $display(i); // and arguments 
  endfunction
endclass

module test();
  initial begin
    base b1,b2;
    b1 = new();
    b2 = new();
    repeat(10) begin
      b1.get();
    end
    $display("@@@@");
    b2.get();
  end
endmodule

Output : 
          1
          2
          3
          4
          5
          6
          7
          8
          9
         10
         11  <--- See this value is incremented

for the class static keyword can be applied on left and right of keyword function. Static written at left implies to lifetime of method with respect to class and it is associated with class type, not with object. It is a method of class type, not of an instance of a class object. Static written at right refers to lifetime of variables and arguments within the method.

Below example will clear this.

class tryfact;
  int i;
  // define the function
  static function integer factorial (input [31:0] operand);
    if (operand >= 2)
    factorial = factorial (operand - 1) * operand;
    else
    factorial = 1;
    //$display("i is %0d",i); This will compilation error. Accessing non-static member in static method.
  endfunction: factorial
endclass

module top();
  // test the function
  tryfact tf;
  integer result;
  initial begin
    //tf = new();
    for (int n = 0; n <= 7; n++) begin
      result = tryfact::factorial(n);
      $display("%0d factorial=%0d", n, result);
    end
  end
endmodule: top

Output :
0 factorial=1
1 factorial=1
2 factorial=2
3 factorial=6
4 factorial=24
5 factorial=120
6 factorial=720
7 factorial=5040

8 comments:

  1. Really best explanation I have ever observed

    ReplyDelete
  2. ya...really great examples thanks

    ReplyDelete
  3. Great explanation, I want to understand a automatic lifetime method is stored in the stack memory then where is the static lifetime method are stored

    ReplyDelete
  4. Thanks for the handy explanation

    ReplyDelete