covergroup: coverpoint binsの記述方法

本記事はSystem Verilogのcovergroupの説明シリーズです。全体でかなりボリュームがあるため、以下に分割しています。上から順番に読んでいただくことをお勧めします。

1. [covergroupの記述方法](https://qiita.com/triggerfish/items/6053d93d99e084e8976f)
* [covergroup: coverpoint binsの記述方法](https://qiita.com/triggerfish/items/5766e890f1d108693a3f)
* [covergroup: cross binsの記述方法](https://qiita.com/triggerfish/items/d2feca30d05e51d3f93b)
* [covergroup: その他の機能とtips](https://qiita.com/triggerfish/items/39ee2ded512fa3df2974)

今回はcoverpoint binsの書き方についてです。

# autobin
カバレッジを収集したい変数、信号等をcoverpointで指定して、何もbinを指定しない場合は自動的にbinが生成されます。coverpointの対象が取りうる全ての値について一つ一つbinが生成されます。ただしデフォルトの最大値は64で、これを超えた場合はなるべく均等になるように64のbinに割り当てます。この数はoption.auto_bin_maxにより変更できます。coverpointの対象としては、信号や変数以外に演算の結果やfunctionの戻り値を指定することができます。またignore_binsを使用することで、その値に対するbinの生成を抑制することができます。

例ではそれぞれのcoverpointの末尾に;がついていたりついていなかったりでややこしいですが、個々のbinを指定しない場合は;をつける、binsを指定する場合は{bins = xxx}で終わらせ、;をつけないという法則になっています。

ignore_binsは特別なbinで、指定された範囲の値はcoverpointから除外されます。

```verilog
  rand logic [3:0] dat1;
  rand logic [3:0] dat2;

  rand enum logic [1:0] {red, yellow, green} flower;

  function logic [2:0] fn();
    return $urandom_range(7,0);
  endfunction

  ...

    abin_1: coverpoint dat1;                     // Automatic bins auto[0], ..., auto[15]
                                                 // Note that max number of bins is 64 by default.
                                                 // It can be changed by option.auto_bin_max property.

    abin_2: coverpoint flower;                   // Automatic bins for enum.
                                                 // auto[red], auto[yellow], auto[green]

    abin_3: coverpoint {1'b0, dat1} + {1'b0, dat2};   // Expressions can be coverpoint as well.
                                                      // Bins will be auto[0], ..., auto[31]

    abin_4: coverpoint fn();                          // Function return value can be a coverpoint.
                                                      // Type of return value of the function is logic [2:0] thus
                                                      // auto[0], ..., auto[7] will be created.

    ign: coverpoint dat1 {
      ignore_bins ign = {[0:7]}; // Value of 0 to 7 will be ignored. Thus bins of auto[8], ..., auto[15] will be generated
    }
```

# binを指定する
## 単独のbin
autobinに頼らず、対象coverpointの値毎にbinを定義することも可能です。この場合binの自動生成は行われず、指定したbinのみが生成されます。そのcoverpoint内のbinに指定されていない値は無視されます。また、一つのcoverpoint内でbinのカバー範囲は重なっていても構いません。その値がヒットした場合はどちらのbinもカウントされます。

* defaultをbinsの右辺に書くと、そのbinはそのcoverpoint内で他のbinでカバーされていないもの全てになります。ただし**defaultを使用したbinはカバレッジの母数に含まれなくなってしまいます。cross coverageの対象にもなりません**。この制限のため、defaultにはあまり使い道が無いです。
* \$は特別な文字で、[\$:3]のように[]内の左側に書くと対象のcoverpointの変域の最小値を示します。同様に[4:\$]のように[]内の右側に書くと対象のcoverpointの変域の最大値を示します。
* illegal_binsは特別なbin名で、そのbinに値がヒットした場合はエラーとなります

```verilog
   logic [3:0] dat1;
   ...
   sbin_2: coverpoint dat1 {
      // Bins can be defined in several styles. Note that bins can overlap
      bins s = {1, 2, 3, 4};   // Bin s that covers 1, 2, 3, and 4
      bins m = {[4:7]};        // Bin m that covers 4 to 7
      bins l = {9, [10:$]};    // Bin l that covers 9 and 10 to maximum value
      bins misc = default;     // Values not covered in other bins, 0 and 8 in this case.
                               // However this bin will not be taken into account for the basement of total coverage
    }

    illegal: coverpoint dat1 {
      illegal_bins ign = {[0:7]}; // Value of 0 to 7 is illegal
    }
```

## Array of bins
bin名に[]を付けるとarrayになります。対象となるcoverpointの変域に応じたbinが自動生成されます。この時のbin数の最大値はスペックには記述が見つかりませんでした。シミュレータ依存となっているようです。
[]の中に数字が入ると、その数だけbinが生成されます。値はなるべく均等になるように割り当てられます。

```verilog
    sbin_auto: coverpoint dat1 {
      bins a[] = {[3:5]};      // Bins of a[3], a[4] and a[5] that cover the value of 3, 4 and 5 individually
      bins b[] = {[1:3], 8};   // Bins of b[1], b[2], b[3], and b[8]
      bins c[2] = {[3:5], 7};  // Bins of c[0] that covers 3, 4 and c[1] that covers 5, 7
    }
```

# ワイルドカード
wildcard binsではワイルドカードを使用することができます。?がワイルドカードの文字となります。

```verilog
    wbin: coverpoint dat1 {
      wildcard bins even = {4'b???0}; // Wildcard is used. dat1 == {0, 2, 4, 6, 8, 10, 12, 14}
      wildcard bins odd = {4'b???1};  // dat1 == {1, 3, 5, 7, 9, 11, 13, 15}
    }
```

# 条件を満たしたときのみcoverageの取得を行う
iffで条件を満たしたときのみcoverageの取得を行うようにすることができます。coverpointとbins双方に付与することができます。iffの条件は信号や変数、functionの戻り値などが使用できます。

```verilog
    iffbin_1: coverpoint dat1 iff (cov_enable); // Conditional coverage collection. Collect coverage only when cov_enable = 1

    iffbin_2: coverpoint dat1 iff (is_cov_enable()) { // Enable condition can be either a function or an expression
      bins s = {[$:7]};
      bins l = {[8:$]};
    }

    iffbin_3: coverpoint dat1 {
      // Conditional coverage collection in bin basis
      bins a = {[0:7]} iff (cov_enable);  // Collect coverage for this bin of "a" only when cov_enable is true
      bins b = {[8:15]};                  // This bin will be always sampled
    }
```

# 条件を満たしたときのみbinを生成する
binsの配列にwithを付与することで、with内の条件を満たしたときのみbinを生成するようにできます。 SV-2012からの機能なので、シミュレータによっては未サポートかもしれません。

```verilog
    cbin_1: coverpoint dat1 {
      // Supported after SV-2012
      // Conditionally generating bins.
      // "item" is a reserved word that represents for coverage variable.
      bins fizz[] = {[0:15]} with (item % 3 == 0);             // fizz[0], fizz[3], ..., fizz[15]
      bins buzz[] = cbin_1 with (item % 5 == 0);               // Use coverpoint name (Here it is "cbin_1") to express the whole value space of this coverpoint.
                                                               // buzz[0], buzz[5], ..., buzz[15]
      bins fizzBuzz[] = cbin_1 with (item % 3 == 0 && item % 5 == 0); // Bin fizzBuzz that covers the value of 0 and 15
    }   
```

#サンプルプログラム。
以上をまとめた、動作するプログラムが以下の通りです。

```verilog
class MyTest;
  rand logic [3:0] dat1;
  rand logic [3:0] dat2;
  rand logic cov_enable;

  rand enum logic [1:0] {red, yellow, green} flower;

  covergroup cg;
    option.per_instance = 1;
    abin_1: coverpoint dat1;                     // Automatic bins auto[0], ..., auto[15]
                                                 // Note that max number of bins is 64 by default.
                                                 // It can be changed by option.auto_bin_max property.

    abin_2: coverpoint flower;                   // Automatic bins for enum.
                                                 // auto[red], auto[yellow], auto[green]

    abin_3: coverpoint {1'b0, dat1} + {1'b0, dat2};   // Expressions can be coverpoint as well.
                                                      // Bins will be auto[0], ..., auto[31]

    abin_4: coverpoint fn();                          // Function return value can be a coverpoint.
                                                      // Type of return value of the function is logic [2:0] thus
                                                      // auto[0], ..., auto[7] will be created.

    ign: coverpoint dat1 {
      ignore_bins ign = {[0:7]}; // Value of 0 to 7 will be ignored. Thus bins of auto[8], ..., auto[15] will be generated
    }
    
    sbin_1: coverpoint dat1 {
      // If bins are declared explicitly, automatic bin will not be generated
      // In this example, only two bins that cover the value of 3 and 5 each are generated
      bins three = {3};
      bins five = {5};
    }

    sbin_2: coverpoint dat1 {
      // Bins can be defined in several styles. Note that bins can overlap
      bins s = {1, 2, 3, 4};   // Bin s that covers 1, 2, 3, and 4
      bins m = {[4:7]};        // Bin m that covers 4 to 7
      bins l = {9, [10:$]};    // Bin l that covers 9 and 10 to maximum value
      bins misc = default;     // Values not covered in other bins, 0 and 8 in this case.
                               // However this bin will not be taken into account for the basement of total coverage
    }

    sbin_auto: coverpoint dat1 {
      bins a[] = {[3:5]};      // Bins of a[3], a[4] and a[5] that cover the value of 3, 4 and 5 individually
      bins b[] = {[1:3], 8};   // Bins of b[1], b[2], b[3], and b[8]
      bins c[2] = {[3:5], 7};  // Bins of c[0] that covers 3, 4 and c[1] that covers 5, 7
    }


    wbin: coverpoint dat1 {
      wildcard bins even = {4'b???0}; // Wildcard is used dat1 == {0, 2, 4, 6, 8, 10, 12, 14}
      wildcard bins odd = {4'b???1};  // dat1 == {1, 3, 5, 7, 9, 11, 13, 15}
    }

    iffbin_1: coverpoint dat1 iff (cov_enable); // Conditional coverage collection. Collect coverage only when cov_enable = 1

    iffbin_2: coverpoint dat1 iff (is_cov_enable()) { // Enable condition can be either a function or an expression
      bins s = {[$:7]};
      bins l = {[8:$]};
    }

    iffbin_3: coverpoint dat1 {
      // Conditional coverage collection in bin basis
      bins a = {[0:7]} iff (cov_enable);  // Collect coverage for this bin of "a" only when cov_enable is true
      bins b = {[8:15]};                  // This bin will be always sampled
    }
    
    cbin_1: coverpoint dat1 {
      // Supported after SV-2012
      // Conditionally generating bins.
      // "item" is a reserved word that represents for coverage variable.
      bins fizz[] = {[0:15]} with (item % 3 == 0);             // fizz[0], fizz[3], ..., fizz[15]
      bins buzz[] = cbin_1 with (item % 5 == 0);               // Use coverpoint name (Here it is "cbin_1") to express the whole value space of this coverpoint.
                                                               // buzz[0], buzz[5], ..., buzz[15]
      bins fizzBuzz[] = cbin_1 with (item % 3 == 0 && item % 5 == 0); // Bin fizzBuzz[0] and fizzBuss[15] that covers the value of 0 and 15
    }   
    
  endgroup

  function logic is_cov_enable();
    return cov_enable;
  endfunction

  function logic [2:0] fn;
    return $urandom_range(7, 0);
  endfunction

  function new();
    cg = new;
  endfunction

  function void run();
    for (int i = 0; i < 10; i++) begin
      randomize();
      cg.sample();
      $display("cov_enable = %b, dat1 = %h, dat2 = %h", cov_enable, dat1, dat2);
    end
  endfunction
endclass

program top;
  initial begin
    MyTest myTest;

    myTest = new;
    myTest.run();
  end
endprogram
```

実行結果のcoverageリポートを抜粋します。

```plaintext
+++++++++++++++++++++++++++++++++++++++++++++
++++++++++       DESIGN UNITS      ++++++++++
+++++++++++++++++++++++++++++++++++++++++++++


CUMULATIVE SUMMARY
=============================================
|    Coverage Type    | Weight | Hits/Total |
=============================================
| Covergroup Coverage |      1 |    66.800% |
|---------------------|--------|------------|
| Types               |        |      0 / 1 |
=============================================
CUMULATIVE DESIGN-BASED COVERAGE: 66.800%
COVERED DESIGN UNITS: 0 / 1
FILES: 1


CLASS - work.MyTest


    SUMMARY
    =============================================
    |    Coverage Type    | Weight | Hits/Total |
    =============================================
    | Covergroup Coverage |      1 |    66.800% |
    |---------------------|--------|------------|
    | Types               |        |      0 / 1 |
    =============================================
    WEIGHTED AVERAGE:  66.800%


    COVERGROUP COVERAGE
    ======================================================================
    |            Covergroup            |   Hits   |  Goal /  |  Status   |
    |                                  |          | At Least |           |
    ======================================================================
    | TYPE /MyTest/cg                  |  66.800% | 100.000% | Uncovered |
    ======================================================================
    | INSTANCE <UNNAMED1>              |  66.800% | 100.000% | Uncovered |
    |----------------------------------|----------|----------|-----------|
    | COVERPOINT <UNNAMED1>::abin_1    |  56.250% | 100.000% | Uncovered |
    |----------------------------------|----------|----------|-----------|
    | bin auto[0]                      |        0 |        1 | Zero      |
    | bin auto[1]                      |        1 |        1 | Covered   |
    | bin auto[2]                      |        1 |        1 | Covered   |
    | bin auto[3]                      |        1 |        1 | Covered   |
    | bin auto[4]                      |        0 |        1 | Zero      |
    | bin auto[5]                      |        0 |        1 | Zero      |
    | bin auto[6]                      |        1 |        1 | Covered   |
    | bin auto[7]                      |        1 |        1 | Covered   |
    | bin auto[8]                      |        1 |        1 | Covered   |
    | bin auto[9]                      |        0 |        1 | Zero      |
    | bin auto[10]                     |        0 |        1 | Zero      |
    | bin auto[11]                     |        0 |        1 | Zero      |
    | bin auto[12]                     |        2 |        1 | Covered   |
    | bin auto[13]                     |        1 |        1 | Covered   |
    | bin auto[14]                     |        1 |        1 | Covered   |
    | bin auto[15]                     |        0 |        1 | Zero      |
    |----------------------------------|----------|----------|-----------|
    | COVERPOINT <UNNAMED1>::abin_2    | 100.000% | 100.000% | Covered   |
    |----------------------------------|----------|----------|-----------|
    | bin auto[red]                    |        4 |        1 | Covered   |
    | bin auto[yellow]                 |        2 |        1 | Covered   |
    | bin auto[green]                  |        4 |        1 | Covered   |
    |----------------------------------|----------|----------|-----------|
    | COVERPOINT <UNNAMED1>::abin_3    |  28.125% | 100.000% | Uncovered |
    |----------------------------------|----------|----------|-----------|
    | bin auto[0]                      |        0 |        1 | Zero      |
    | bin auto[1]                      |        0 |        1 | Zero      |
    | bin auto[2]                      |        0 |        1 | Zero      |
    | bin auto[3]                      |        2 |        1 | Covered   |
    | bin auto[4]                      |        0 |        1 | Zero      |
    | bin auto[5]                      |        0 |        1 | Zero      |
    | bin auto[6]                      |        0 |        1 | Zero      |
    | bin auto[7]                      |        0 |        1 | Zero      |
    | bin auto[8]                      |        0 |        1 | Zero      |
    | bin auto[9]                      |        0 |        1 | Zero      |
    | bin auto[10]                     |        1 |        1 | Covered   |
    | bin auto[11]                     |        1 |        1 | Covered   |
    | bin auto[12]                     |        0 |        1 | Zero      |
    | bin auto[13]                     |        0 |        1 | Zero      |
    | bin auto[14]                     |        1 |        1 | Covered   |
    | bin auto[15]                     |        1 |        1 | Covered   |
    | bin auto[16]                     |        0 |        1 | Zero      |
    | bin auto[17]                     |        0 |        1 | Zero      |
    | bin auto[18]                     |        0 |        1 | Zero      |
    | bin auto[19]                     |        0 |        1 | Zero      |
    | bin auto[20]                     |        1 |        1 | Covered   |
    | bin auto[21]                     |        0 |        1 | Zero      |
    | bin auto[22]                     |        1 |        1 | Covered   |
    | bin auto[23]                     |        1 |        1 | Covered   |
    | bin auto[24]                     |        0 |        1 | Zero      |
    | bin auto[25]                     |        1 |        1 | Covered   |
    | bin auto[26]                     |        0 |        1 | Zero      |
    | bin auto[27]                     |        0 |        1 | Zero      |
    | bin auto[28]                     |        0 |        1 | Zero      |
    | bin auto[29]                     |        0 |        1 | Zero      |
    | bin auto[30]                     |        0 |        1 | Zero      |
    | bin auto[31]                     |        0 |        1 | Zero      |
    |----------------------------------|----------|----------|-----------|
    | COVERPOINT <UNNAMED1>::abin_4    |  50.000% | 100.000% | Uncovered |
    |----------------------------------|----------|----------|-----------|
    | bin auto[0]                      |        0 |        1 | Zero      |
    | bin auto[1]                      |        0 |        1 | Zero      |
    | bin auto[2]                      |        1 |        1 | Covered   |
    | bin auto[3]                      |        5 |        1 | Covered   |
    | bin auto[4]                      |        0 |        1 | Zero      |
    | bin auto[5]                      |        1 |        1 | Covered   |
    | bin auto[6]                      |        0 |        1 | Zero      |
    | bin auto[7]                      |        3 |        1 | Covered   |
    |----------------------------------|----------|----------|-----------|
    | COVERPOINT <UNNAMED1>::ign       |  50.000% | 100.000% | Uncovered |
    |----------------------------------|----------|----------|-----------|
    | bin auto[8]                      |        1 |        1 | Covered   |
    | bin auto[9]                      |        0 |        1 | Zero      |
    | bin auto[10]                     |        0 |        1 | Zero      |
    | bin auto[11]                     |        0 |        1 | Zero      |
    | bin auto[12]                     |        2 |        1 | Covered   |
    | bin auto[13]                     |        1 |        1 | Covered   |
    | bin auto[14]                     |        1 |        1 | Covered   |
    | bin auto[15]                     |        0 |        1 | Zero      |
    | ignore bin ign                   |        5 |    -     | Occurred  |
    |----------------------------------|----------|----------|-----------|
    | COVERPOINT <UNNAMED1>::sbin_1    |  50.000% | 100.000% | Uncovered |
    |----------------------------------|----------|----------|-----------|
    | bin three                        |        1 |        1 | Covered   |
    | bin five                         |        0 |        1 | Zero      |
    |----------------------------------|----------|----------|-----------|
    | COVERPOINT <UNNAMED1>::sbin_2    | 100.000% | 100.000% | Covered   |
    |----------------------------------|----------|----------|-----------|
    | bin s                            |        3 |        1 | Covered   |
    | bin m                            |        2 |        1 | Covered   |
    | bin l                            |        4 |        1 | Covered   |
    | default bin misc                 |        1 |    -     | Occurred  |
    |----------------------------------|----------|----------|-----------|
    | COVERPOINT <UNNAMED1>::sbin_auto |  77.777% | 100.000% | Uncovered |
    |----------------------------------|----------|----------|-----------|
    | bin a[3]                         |        1 |        1 | Covered   |
    | bin a[4]                         |        0 |        1 | Zero      |
    | bin a[5]                         |        0 |        1 | Zero      |
    | bin b[1]                         |        1 |        1 | Covered   |
    | bin b[2]                         |        1 |        1 | Covered   |
    | bin b[3]                         |        1 |        1 | Covered   |
    | bin b[8]                         |        1 |        1 | Covered   |
    | bin c[0]                         |        1 |        1 | Covered   |
    | bin c[1]                         |        1 |        1 | Covered   |
    |----------------------------------|----------|----------|-----------|
    | COVERPOINT <UNNAMED1>::wbin      | 100.000% | 100.000% | Covered   |
    |----------------------------------|----------|----------|-----------|
    | bin even                         |        6 |        1 | Covered   |
    | bin odd                          |        4 |        1 | Covered   |
    |----------------------------------|----------|----------|-----------|
    | COVERPOINT <UNNAMED1>::iffbin_1  |  31.250% | 100.000% | Uncovered |
    |----------------------------------|----------|----------|-----------|
    | bin auto[0]                      |        0 |        1 | Zero      |
    | bin auto[1]                      |        1 |        1 | Covered   |
    | bin auto[2]                      |        0 |        1 | Zero      |
    | bin auto[3]                      |        1 |        1 | Covered   |
    | bin auto[4]                      |        0 |        1 | Zero      |
    | bin auto[5]                      |        0 |        1 | Zero      |
    | bin auto[6]                      |        1 |        1 | Covered   |
    | bin auto[7]                      |        1 |        1 | Covered   |
    | bin auto[8]                      |        1 |        1 | Covered   |
    | bin auto[9]                      |        0 |        1 | Zero      |
    | bin auto[10]                     |        0 |        1 | Zero      |
    | bin auto[11]                     |        0 |        1 | Zero      |
    | bin auto[12]                     |        0 |        1 | Zero      |
    | bin auto[13]                     |        0 |        1 | Zero      |
    | bin auto[14]                     |        0 |        1 | Zero      |
    | bin auto[15]                     |        0 |        1 | Zero      |
    |----------------------------------|----------|----------|-----------|
    | COVERPOINT <UNNAMED1>::iffbin_2  | 100.000% | 100.000% | Covered   |
    |----------------------------------|----------|----------|-----------|
    | bin s                            |        4 |        1 | Covered   |
    | bin l                            |        1 |        1 | Covered   |
    |----------------------------------|----------|----------|-----------|
    | COVERPOINT <UNNAMED1>::iffbin_3  | 100.000% | 100.000% | Covered   |
    |----------------------------------|----------|----------|-----------|
    | bin a                            |        4 |        1 | Covered   |
    | bin b                            |        5 |        1 | Covered   |
    |----------------------------------|----------|----------|-----------|
    | COVERPOINT <UNNAMED1>::cbin_1    |  25.000% | 100.000% | Uncovered |
    |----------------------------------|----------|----------|-----------|
    | bin fizz[0]                      |        0 |        1 | Zero      |
    | bin fizz[3]                      |        1 |        1 | Covered   |
    | bin fizz[6]                      |        1 |        1 | Covered   |
    | bin fizz[9]                      |        0 |        1 | Zero      |
    | bin fizz[12]                     |        2 |        1 | Covered   |
    | bin fizz[15]                     |        0 |        1 | Zero      |
    | bin buzz[0]                      |        0 |        1 | Zero      |
    | bin buzz[5]                      |        0 |        1 | Zero      |
    | bin buzz[10]                     |        0 |        1 | Zero      |
    | bin buzz[15]                     |        0 |        1 | Zero      |
    | bin fizzBuzz[0]                  |        0 |        1 | Zero      |
    | bin fizzBuzz[15]                 |        0 |        1 | Zero      |
    ======================================================================
```

EDA playgroundにプログラム一式があるので、実際に動作させることもできます。
[covergroup bins](https://www.edaplayground.com/x/2w7f)
実行後にダウンロードされるファイルの中にあるcov.txtがカバレッジのリポートとなります。

# 参考文献
 "19 Functional coverage". [1800-2017 - IEEE Standard for SystemVerilog--Unified Hardware Design, Specification, and Verification Language](https://doi.org/10.1109/IEEESTD.2018.8299595). pp.553-590.