可参数化的交叉长度

时间:2017-10-25 07:09:31

标签: system-verilog

我有一个支持突发的协议,每个事务由N个人传输组成。每次转移都有一个从0N-1的唯一索引。我想要了解所有转移订单(即0 1 2 31 2 3 00 2 3 1等)。 N的值是可变的(尽管在我的情况下我现在只关心4和8)。

天真的方法是单独覆盖每个索引并跨越它们,但这意味着我需要多个covergroups,每个值N一个。

N = 4

covergroup some_cg;
  coverpoint idxs[0];
  coverpoint idxs[1];
  coverpoint idxs[2];
  coverpoint idxs[3];

  cross idxs[0], idxs[1], idxs[2], idxs[3] {
    ignore_bins non_unique_idxs[] = some_func_that_computes_bins_for_4_idxs();
  }
endgroup

N = 8

covergroup some_cg;
  coverpoint idx[0];
  coverpoint idx[1];
  coverpoint idx[2];
  coverpoint idx[3];
  coverpoint idx[4];
  coverpoint idx[5];
  coverpoint idx[6];
  coverpoint idx[7];

  cross idx[0], idx[1], idx[2], idx[3], idx[4], idx[5], idx[6], idx[7] {
    ignore_bins non_unique_idxs[] = some_func_that_computes_bins_for_8_idxs();
  }
endgroup

生成忽略区的两个函数每个都必须返回不同的类型(struct和4/8字段的队列),即使在概念上计算所有非法组合的操作是相似的,无论值是多少N。这可以通过巧妙地使用流操作符来解决,以将structs的内容流式传输到N元素的数组中。尽管如此,covergroup定义中的冗余问题仍然存在。我能想到解决这个问题的唯一方法就是生成代码。

另一个想法是将所有索引打包成适当大小的打包数组,并涵盖:

covergroup some_other_cg;
  coverpoint packed_idxs {
    ignore_bins non_unique_idxs[] = some_func_that_computes_bins_for_N_idxs();
  }
endgroup

// Probably won't compile, but it would also be possible to use the streaming op
// Idea is to pack into integral type
foreach (idxs[i])
  packed_idxs[i * idx_len +: len] = idxs[i];

调试覆盖漏洞很痛苦,因为很难确定某个打包值属于哪个转移顺序,特别是如果值以十进制基数显示。我相信值的显示方式因工具而异,因此无法控制。我也认为没有任何可能使用字符串为各个箱子命名。

我欢迎任何可以改进这两项建议的投入。目标是让一个覆盖包装类具有传输次数的参数,并能够实例化并获得覆盖:

class transfer_orders_coverage #(int unsigned NUM_TRANSFERS);
  // ...
endclass

2 个答案:

答案 0 :(得分:1)

添加和'回答'因为评论太久了。如果我不清楚,请原谅我。

你可以在采样CG之前添加一些逻辑 并使用一些表示idxs数组位置的输入参数吗?对于十字架,您可以维护大小为N 的打包数组,并在检测到特定模式时创建单独的位1。在sim结束时,您可以在某些不同的CG中对该模式的覆盖率进行采样。

基本上,我们的想法是卸载封面组内的逻辑并添加围绕sample功能的逻辑。这是一个关于我在想什么的粗略想法。

class transfer_orders_coverage #(int unsigned N = 4);
  int idxs[N];
  bit [(N -1) : 0] pattern; // Make indexes HIGH according to sampled pattern
  // ...
  covergroup cross_cg;
    mycp_cross: coverpoint pattern{
      ignore_bins myignbn = {some_generic_function_for_N(pattern)};
    }
  endgroup

  covergroup indiv_cg with function sample (int index);
      mycp_indiv: coverpoint idxs[index]{
                    // some bins to be covered in ith position of idxs
                  }
  endgroup

  function new();
    cross_cg = new;
    indiv_cg = new;
  endfunction

  function bit [(N -1) : 0] some_generic_function_for_N(bit [(N -1) : 0] pattern);
    // check which bits in "pattern" are to be covered and which are to be ignored 
    //return some_modified_pattern;
  endfunction

  function void start();
    // Any logic for sampling ith position
    foreach(idxs[i]) begin
      indiv_cg.sample(i);
      pattern[i] = 1'b1;
    end
    cross_cg.sample();

  endfunction

endclass

module top();
  transfer_orders_coverage #(4) tr;
  initial begin
    tr = new;
    tr.start();
  end
endmodule

让我知道它是否可行。

答案 1 :(得分:0)

我想,以下解决方案可能适用于这种情况。

covergroup some_cg (int num);
  4n_cp : coverpoint ({idxs[0], idxs[1], idxs[2], idxs[3]}) iff (num == 4)
  {
    option.weight = (num == 4) ? 1 : 0; // Weight might change depending on other coverpoints
    ignore_bins non_unique_index[] = <Your Function>;
  }

  8n_cp : coverpoint ({idxs[0], idxs[1], idxs[2], idxs[3], idxs[4], idxs[5], idxs[6], idxs[7]}) iff (num == 8)
  {
    option.weight = (num == 8) ? 1 : 0; // Weight might change depending on other coverpoints
    ignore_bins non_unique_index[] = <Your Function>;
  }
endgroup

// Where you instantiate covergroups 
some_cg c1 = new(4);

让我知道,上述想法是如何运作的。