Sunday, 29 March 2015

Compilation switches vs Simulation switches in SystemVerilog

Compilation Switches:

Verilog has following conditional compiler directives. 
  • `ifdef
  • `else
  • `elsif
  • `endif
  • `ifndef
The `ifdef compiler directive checks for the definition of a text_macro_name. If the text_macro_name is defined, then the lines following the `ifdef directive are included. If the text_macro_name is not defined and an `else directive exists, then this source is compiled.

The `ifndef compiler directive checks for the definition of a text_macro_name. If the text_macro_name is not defined, then the lines following the `ifndef directive are included. If the text_macro_name is defined and an `else directive exists, then this source is compiled.

If the `elsif directive exists (instead of the `else) the compiler checks for the definition of the text_macro_name. If the name exists the lines following the `elsif directive are included. The `elsif directive is equivalent to the compiler directive sequence `else `ifdef ... `endif. This directive does not need a corresponding `endif directive. This directive must be preceded by an `ifdef or `ifndef directive.


The code written within the compilation flags are compiled at compilation period.
As a result, the executable file creates a snap-shot of that particular code written within the compile flag.
For example, please go through below code.
LINE 1 :                     module xyz ()
LINE 2 :                        `ifdef FIRST
LINE 3 :                           $display ("Inside FIRST");
LINE 4 :                        `elseif SECOND
LINE 5 :                           $display ("Inside SECOND");
LINE 6 :                        `elseif THIRD
LINE 7 :                           $display ("Inside THIRD");
LINE 8 :                        `else
LINE 9 :                           $display ("Inside ELSE");
LINE 10 :                     `endif
LINE 11 :                     $display ("Inside LAST");
LINE 12 :                   endmodule  : xyz

 
Now compile the code with define "+define+FIRST".

The executable file will contains snapshot of "LINE 3 & LINE 11"
Now simulating the executable file, output will be as:
Inside FIRST
Inside LAST

 
Now we re-simulate(without compiling again), and pass define "+define+SECOND" at run time, output will be as:
Inside FIRST
Inside LAST

 
Now we re-simulate(without compiling again), without passing any defines at run time, output will be as:
Inside FIRST
Inside LAST

 
If we required to display "LINE 5" we have to re-compile complete testbench with +define+SECOND at compile time
Now simulating the executable file, output will be as:
Inside SECOND
Inside LAST



Simulation Switches:


Variable ( int i  /  string abc ) are used as simulation flag
The complete testbench will be compiled at one-shot, and the executable file will contains snap-shot of complete codes.
For example, please go through below code.

LINE 1 :                     module xyz ();
LINE 2:                         reg [1:0] arg;
LINE 3 :                        if ($value$plusargs("argument=%0d",arg));
LINE 4 :                            if(arg == 1)
LINE 5 :                              $display ("Inside FIRST");
LINE 6 :                           else if(arg == 2)

LINE 7 :                              $display ("Inside SECOND");
LINE 6 :                           else if(arg == 3)
LINE 7 :                              $display ("Inside THIRD");
LINE 8 :                           else
LINE 9 :                              $display ("Inside ELSE");
LINE 10 :                      end
LINE 11 :                     $display ("Inside LAST");
LINE 12 :                   endmodule : xyz



Now compile the testbench without any arguments . The executable file contains snap-shot of all complete lines mention in module.
Now simulating the executable file, and we provide argument "+argument=1" at runtime  output will be as:
Inside FIRST
Inside LAST


Now we re-simulate(without compiling again), and we provide argument +argument=2, at runtime  output will be as:
Inside SECOND
Inside LAST

 
Now we re-simulate(without compiling again), and we provide argument +argument=3, at runtime  output will be as:
Inside THIRD
Inside LAST

 
Now we re-simulate(without compiling again) without any argument, at runtime  output will be as:
Inside LAST

 
As we saw, the benefits of "$values$plusargs" is:
One time compiling (creating executable file) and running multiple testcase on same executable file.


Now for environmental Modification, It is very necessary to reduce down the usage of (`ifdef / `elseif ) to very minimum and try to use simulation time arguments as much as possible. And at the same time we need to take care of single Test run but on other side it will be very much help full for (One time compilation with multisimulation) regression.

With the above style of programing,we can save recompilation times.

Difference between $test$plusargs and $value$plusargs:

There are two types of Simulation switches in systemverilog.

$value$plusargs:
We have seen example of $value$plusargs in above explaination. In $value$plusargs user need to pass value in argument and based on that value some decision will be taken.
We will go through another example:
module valuetest();
  integer i;
  real r;
  reg [11:0] v;
  reg [128:0] s;

  initial begin
    if($value$plusargs("STRING=%s", s))
      $display("GOT STRING");
    if($value$plusargs("INTG=%d", i))
      $display("GOT INTEGER");
    if($value$plusargs("REAL=%f", r))
      $display("GOT REAL");
    if($value$plusargs("VECTOR=%b", v))
      $display("GOT VECTOR");

    $display( "String is %s", s);
    $display("Integer is %d", i);
    $display("Realnum is %f", r);
    $display("Vector is %b", v);
  end
endmodule

Compilation:
command filename.sv
Simulation:
command +STRING=rrf  +INTG=123  +REAL=1.32  +VECTOR=10101

RESULTS:
GOT STRING
GOT INTEGER
GOT REAL
GOT VECTOR
String is rrf
Integer is 123
Realnum is 1.320000e+00
Vector is 000000010101 
$test$plusargs:
In $test$plusargs user don't need to give value in argument. If user provides simulation argument in simulation command then if condition will be executed otherwise else part (if exists) will be executed.
Example:
module switches();
  initial begin

    if($test$plusargs("TYPE_1"))
      $display("TYPE_1 message");
    else
      if($test$plusargs("TYPE_2"))

        $display("TYPE_2 message");
  end
endmodule
 
No need to give +define+TYPE_1 or +define+TYPE_2 during compilation

Simulate with +TYPE_1
RESULT:
TYPE_1 message

Simulate with +TYPE_2
Then simulate,result is
RESULT:
TYPE_2 message



Benefits & disadvantage of Compilation/Simulation Switches:

If we use Compilation switches:

  1. For Single Test run:
    1. Compilation and simulation time reduces. because the very small amount of code will be exercised. 
  2. For Regression: 
    1. If their are defines for each test case / test command we have to COMPILE & SIMULATE each testcase.

If we use Simulation switches:

  1. For Single Test run: 
    1. Compilation time increases (because complete code is getting exercised) and simulation time remains same.
  2. For Regression: 
    1. We have to compile one time, and we can use same executable file for all the test cases / test commands.

4 comments: