Tuesday, 2 October 2018

Passing Multiple Enum through command line using UVM1.2

This post is related to my previous blog "http://munjalm.blogspot.com/2018/09/passing-enum-through-command-line_2.html" which describes passing enum through command line.

Consider a case where, user wants to randomize enum from few enum values only. In this case, multiple enums can be passed through command line using a delimiter. For example, +DATA_TYPE=DT_2,DT_4.

As "from_name" function converts the string into enum, the above string can be separated out and can be used in "from_name" to get the enum values. To get substring from a string, there are multiple ways:
(1) System verilog provides "substr" function through which we can get the substring. But in the case, we shall know the exact location from where we can the substring.
(2) Go through each character of a string and compare each character with delimiter. If it matches then separate out the sub string.

Here, UVM provides "uvm_split_string" function which splits the string based on a delimiter and returns a queue with sub string. This function contains 3 arguments which are described below:
First arg (string): Main string which will be divided into multiple string
Second arg(byte): Delimiter from where the main string will be separated
Third arg(string queue): It's a reference variable which contains all sub-strings separated with delimiter from main string.

Below is the example which helps to understand more:

Example:
  typedef enum {DT_1, DT_2, DT_3, DT_4} data_type_e;
  typedef uvm_enum_wrapper#(data_type_e) uvm_dt;
  data_type_e dt, dt_1;
  string str;

  initial begin
      string str_q[$];
      data_type_e dt_q[$];

      void'($value$plusargs("DATA_TYPE=%0s", str));

      uvm_split_string(str, ",", str_q);

      foreach (str_q[i]) begin
          if(!(uvm_dt::from_name(str_q[i], dt))) begin
              $display("Wrong Data Type Provided.");
          end
          else begin
              $display("Data Type=%0s",dt.name());
              dt_q.push_back(dt);
          end
      end
      foreach(dt_q[i]) $display("DT=%0s",dt_q[i].name());
      for(int i = 0; i < 10; ++i) begin
          if(!randomize(dt_1) with {dt_1 inside {dt_q};})
              $error("Randomization Failed.");
          else
              $display("Randomized DT=%0s", dt_1.name());
      end
  end

Command with Questa-tool:
vsim "+DATA_TYPE=DT_2,DT_4" -c -do "run -all;q" -f questa.tops

When above command is executed, dt_l value will be generated from DT_2 or DT_4 enum during randomization. 
Here, "DT_2,DT_4" is taken as a single string and is splitted across multiple string using "uvm_split_string" function and the splitted string is stored in "str_q" queue. Then the splitted string is converted into enum using "from_name" function and stored into "dt_q" queue from which dt_l is randomized.



Sunday, 2 September 2018

Passing enum through command line argument using UVM 1.2

In verification activity, many of us came across a situation where we need to regenerate bugs with specific scenario or to achieve coverage, we need to create scenario with specific value. In this case, generalized sequences are very useful which takes command line arguments as input and generate those scenarios. So we don't need to modify the existing code or don't require to code new scenarios.

Data types like int or string can be easily passed through command line argument and the value is get into the code using "$value$plusargs" system verilog function. 

Now, consider a case where a scenario required with specific enum value. System verilog doesn't support for providing enum name through command line argument directly. So in that case, either string shall be passed through command line and it shall be converted into enum in the code or enum type shall be passed through command line and it shall be cast to enum type. 

In UVM 1.2, a feature is added for passing enum through command line and let's explore this feature with detail example: 

In the below example, an enum "data_type_e" is declared and to get its value through command line argument, it is defined with "uvm_enum_wrapper" as this class contains method "from_name" through which any argument passed as a string through command line, can be converted into the defined enum. Here, any enum values can be passed through command line argument as a string and in the code it gets as a string using "$value$plusargs" and the string is passed through "from_name" function to get its correct enum value and it can be used in the code. If enum value is not defined then this function returns 0. 

Example:
  typedef enum {DT_1, DT_2, DT_3, DT_4} data_type_e;
  typedef uvm_enum_wrapper#(data_type_e) uvm_dt;
  data_type_e dt;
  string str;

  initial begin
    void'($value$plusargs("DATA_TYPE=%0s", str));

    if(!(uvm_dt::from_name(str, dt)))
      $display("Wrong Data Type Provided.");
    else
      $display("Data Type=%0s",dt.name());

While simulating above code with command line argument  "+DATA_TYPE=DT_4", it receives DT_4 enum value. Here, DT_5 is passed which is not a part of enum values then "from_name" will return 0.

Command with Questa Tool:
vsim "+DATA_TYPE=DT_4" -c -do "run -all; q"  -f questa.tops

Output:
Data Type=DT_4