如何覆盖请求和响应之间的延迟

时间:2016-06-25 04:54:59

标签: system-verilog function-coverage

假设我们有一个协议,其中请求reqreq_id断言,相应的rsp将与rsp_id断言。这些可能是乱序的。我想要涵盖具有相同ID的req与特定req_idrsp之间的clks数或延迟。我试过这样的事。这是正确的做法吗?还有其他有效的方法吗?

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

3 个答案:

答案 0 :(得分: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将请求与响应分开。

答案 1 :(得分: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);

答案 2 :(得分:0)

或者......

属性/序列虽然它们似乎是小代码,在这种情况下对于每个req(尚未接收到rsp),分叉的单独进程与其自己的计数器。这导致许多计数器做了非常相似的工作。如果飞行中有许多req(和/或属性或序列的许多实例),它将开始添加到模拟运行时[尽管这只是一小段代码]

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

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介入以节省一天:)