我有一个支持突发的协议,每个事务由N
个人传输组成。每次转移都有一个从0
到N-1
的唯一索引。我想要了解所有转移订单(即0 1 2 3
,1 2 3 0
,0 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
答案 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);
让我知道,上述想法是如何运作的。