Skip to content

Releases: amiq-consulting/fc4sc

FC4SC_v2.1.1: Merge pull request #7 from amiq-consulting/flexible_bin_definitions

02 Nov 17:45
3da19f7
Compare
Choose a tag to compare

Flexible bin creation

01 Nov 17:19
Compare
Choose a tag to compare
Flexible bin creation Pre-release
Pre-release

New way to flexibly create bins

The bin_array can now be constructed from a std::vector of either

  • intervals : std::vector<fc4sc::interval_t<T>>
  • values : std::vector<T>

The result is that for each value/interval from the vector passed to the bin_array constructor, a different bin will be created in the coverpoint.
This can be used together with a function which returns a vector of intervals or values in order to more flexibly create coverpoint bins.

Values Example:

// lambda function returning a vector of N fibonacci numbers generated by starting with 1 and 2
auto fibonacci = [](size_t N) -> std::vector<int> {
  // start with 1 and 2, so that we don't have repeating elements
  int f0 = 1, f1 = 2;
  // resulting vector containing all generated values
  std::vector<int> result(N, f0);

  for (size_t i = 1; i < N; i++) {
    std::swap(f0, f1);
    result[i] = f0;
    f1 += f0;
  }
  return result;
};

class flexible_bin_array_cvg: public covergroup {
private:
  int val = 0;
public:
  CG_CONS(flexible_bin_array_cvg) {};
  COVERPOINT(int, bin_array_cvp, val) {
    // this bin_array expands to 5 different bins for values: 1, 2, 3, 5, 8
    bin_array<int>("fibonacci", fibonacci(5))
  };
  void sample(int val) { this->val = val; sample(); }
};

Intervals Example:

// returns the first N fibonacci intervals, starting with 1 and 2
// a fibonacci interval is an interval of form [f0+1, f1],
// where f0 and f1 are successive fibonacci numbers
auto fibonacci_intervals = [](size_t N) -> std::vector<fc4sc::interval_t<int>> {
  int f0 = 1, f1 = 2; // starting numbers
  std::vector<fc4sc::interval_t<int>> result(N, interval(f0, f1));

  for (size_t i = 1; i < N; i++) {
    std::swap(f0, f1);
    f1 += f0;
    result[i] = interval(f0+1, f1);
  }
  return result;
};
class flexible_bin_array_cvg: public covergroup {
private:
  int val = 0;
public:
  CG_CONS(flexible_bin_array_cvg) {};
  COVERPOINT(int, bin_array_cvp, val) {
    // this bin_array expands to 10 different bins for the following intervals
    // {[1:2], [3:3], [4:5], [6:8], [9:13], [14:21], [22:34], [35:55], [56:89], [90:144]}
    bin_array<int>("fibonacci_intervals", fibonacci_intervals(10))
  };
  void sample(int val) { this->val = val; sample(); }
};

Fix for the bin_array interval splitting method

The functionality of bin_array for splitting an interval has now been fixed to properly slice the interval according to the method described in the IEEE 1800-2012 - IEEE Standard for SystemVerilog:

If the number of automatic bins is smaller than the number of possible values (N < 2^M), then the 2^M values
are uniformly distributed in the N bins. If the number of values, 2^M, is not divisible by N, then the last bin
will include the additional remaining items. For example, if M is 3 and N is 3, then the eight possible values
are distributed as follows: <0:1>, <2:3>, <4,5,6,7>.

Example:

bin_array<int>("1_to_5", 5, interval(1,5));
// previously would result in: {[1:2], [2:3], [3:4], [4:5], 5}
// now correctly results in : {1,2,3,4,5}

This means that bin_arrays will now possibly split intervals into pieces differently, compared to previous FC4SC versions.

Coverpoint definition improvements

09 Oct 09:52
Compare
Choose a tag to compare

This release contains new functionality and changes that add to the quality of the library.
See details below.

New Coverpoint definition method

New

int data_value = 0;
// The coverpoint samples the value returned by the evaluation of the "data_value * 2" expression.
// The evaluation is done at the call to the sample() function of the parent covergroup.
COVERPOINT(int, data_cvp, data_value * 2) {
    illegal_bin<int>("illegal_zero", 0),
    bin<int>("positive", interval(1,INT_MAX)),
    bin<int>("negative", interval(-1,INT_MIN))
};

Old

// Step 2: bind variable to coverpoint
int SAMPLE_POINT(data_value, data_cvp);
// Step 1:  declare coverpoint
coverpoint<int> data_cvp = coverpoint<int> (
    this,
    illegal_bin<int>("illegal_zero", 0),
    bin<int>("positive", interval(1,INT_MAX)),
    bin<int>("negative", interval(-1,INT_MIN))
);
// Step 3: update coverpoint variable and sample it 
void sample(int data) {
    this->data_value = data;
    covergroup::sample();
}

Benefits for the new syntax:

  1. Gets rid of the extra step of using SAMPLE_POINT(...)) macro which has the following problems:
    • A segmentation fault would be generated if SAMPLE_POINT(...); was declared after its associated coverpoint is instantiated (Note above: Step 2 precedes Step 1)
    • Relied on the user manually binding a sample variable to the coverpoint, which is error prone
    • Restricted sampling to be made on the value of a variable, not supporting complex/compound expressions
  2. Adds support for sample expressions & sample conditions
  3. Custom covergroup sample function is no longer required
  4. It is much clearer, easier to use and much more similar to SystemVerilog standard coverpoint definitions.

The old definition syntax is still (currently) supported, but considered deprecated and will be removed in the future!

Sample condition example

int data_value = 0;
int threshold = 0;
// The 4th argument represents the sample condition. Similar to sample expression, the condition 
// is evaluated and checked at the call to the sample() function of the parent covergroup.
// In this case, the coverpoint is sampled if the value of the threshold variable is bigger than 50.
COVERPOINT(int, data_cvp, data_value * 2, threshold > 50) {
    illegal_bin<int>("illegal_zero", 0),
    bin<int>("positive", interval(1,INT_MAX)),
    bin<int>("negative", interval(-1,INT_MIN))
};

New Coverpoint definition restriction

Coverpoints must contain at least one bin; Empty coverpoints are no longer allowed!
Note: this constraint is valid for the new definition method only!

New Bin definition restrictions

  • Bin name must now be specified; Unnamed bins are no longer allowed!
    • Note: The name must be the first argument to the constructor!
  • The bin must contain at least one value/interval; Empty bins are no longer allowed!

Example:

auto my_bin = bin<int>(
    "power_of_2",
    1,              // {1}
    interval(2,3),  // [2:3]
    interval(7,4),  // [4:7]
    interval(15,8)  // [8:15]
);

If any of the coverpoint/bin definition restrictions are not met, compilation will fail!