2

Let's say we have a protocol where request req is asserted with req_id and corresponding rsp will be asserted with rsp_id. These can be out of order. I want to cover the number of clks or latency between req with particular req_id and rsp with the same id. I tried something like this. Is this correct way of doing? Is there any other efficient way?

covergroup cg with function sample(int a);
  coverpoint a {
  a1: bins short_latency = {[0:10]};
  a2: bins med_latency = {[11:100]};
  a3: bins long_latency = {[101:1000]};
  }
endgroup
// Somewhere in code
cg cg_inst = new();

sequence s;
  int lat;
  int id;
  @(posedge clk) disable iff (~rst)
    (req, id = req_id, lat = 0) |-> ##[1:$] ((1'b1, lat++) and (rsp && rsp_id == id, cg_inst.sample(lat)));
endsequence
4

3 回答 3

2

您正在尝试|->在序列中使用运算符,这仅允许在属性中使用。

如果rsp只能在 之后出现一个周期req,那么这段代码应该可以工作:

property trans;
    int lat, id;

    (req, id = req_id, lat = 0) |=> (1, lat++) [*0:$] ##1 rsp && rsp_id == id
      ##0 (1, $display("lat = %0d", lat));
endproperty

之后的元素##0用于调试。您可以在生产代码中省略它。

不过,我不会像这样混合断言和覆盖,因为我已经看到蕴涵运算符可能会导致变量流出现问题(即lat不会正确更新)。您应该有一个属性,该属性仅涵盖您在请求后看到的匹配响应:

property cov_trans;
    int lat, id;

    (req, id = req_id, lat = 0) ##1 (1, lat++) [*0:$] ##1 rsp && rsp_id == id
      ##0 (1, $display("cov_lat = %0d", lat));
endproperty

cover property (cov_trans);

请注意,我曾经##1将请求与响应分开。

于 2016-06-26T10:07:55.650 回答
0

基本上你的想法是正确的,但是当条件为真时,看起来序列的右侧将被评估一次,因此 lat 只会增加一次。

您将需要一个循环机制来计算延迟。

下面是一个示例工作示例。您可以根据生成信号的接近程度更改 [1:$]、##1 等

property ps;
  int lat;
  int id;
  @(posedge clk)
     disable iff (~rst)
        (req, id = req_id, lat = 0) |=> (1'b1, lat++)[*1:$] ##1 (rsp && rsp_id == id, cg_inst.sample(lat));
endproperty

assert property (ps);
于 2016-06-26T02:07:33.153 回答
0

或者...

属性/序列虽然它们看起来是小代码,但在这种情况下,对于每个 req (尚未收到 rsp ),一个带有自己计数器的单独进程被分叉。这导致许多计数器做非常相似的工作。如果有很多请求(和/或属性或序列的许多实例),它将开始添加到模拟运行时[即使这只是一小段代码]

所以另一种方法是保持触发器更简单,我们尝试保持处理线性。

int counter=0; // you can use a larger variablesize to avoid the roll-over issue
int arr1[int] ;  // can use array[MAX_SIZE] if you know the max request id is small
always @( posedge clk ) counter <= counter + 1 ; // simple counter 


function int latency (int type_set_get , int a ) ;
    if ( type_set_get == 0 ) arr1[a] = counter; // set
                                 //DEBUG $display(" req id %d latency %d",a,counter-arr1[a]);
                                 // for roll-over - if ( arr1[a] > counter ) return ( MAX_VAL_SIZE  - arr1[a] + counter ) ; 
   return (counter - arr1[a]);  //return the difference between captured clock and current clock .
endfunction

property ps();
  @(posedge clk) 
     disable iff (~rst) 
         ##[0:$]( (req,latency(0,req_id) ) or  (rsp,cg_inst.sample(latency(1,rsp_id))) );
endproperty

assert property (ps);

仅当看到 req/rsp 并且只有 1 个线程在寻找它时才会触发上述属性。如果需要,可以在函数中添加额外的检查,但是对于延迟计数,这应该没问题。

轶事:

Mentor AE-Dan 发现了一个断言,它使我们的模拟速度降低了 40%。写得不好的断言是我们块 tb 的一部分,它的影响在那里没有被注意到,因为我们的块级测试,运行时间是有限的。然后它潜入我们的顶级 tb 造成无法估量的运行时损失,直到一年后才被发现:)。[猜想我们应该早点分析我们的模拟运行]

比方说,如果上面的协议稍后实现了中止,那么 req-rsp 线程将继续处理并等待(直到模拟结束)中止的事务,虽然它不会影响功能,但它会偷偷地继续占用处理器资源而无用作为回报。直到最后一个供应商 AE 介入以挽救这一天:)

于 2016-06-26T16:36:35.843 回答