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
user1978273
  • 484
  • 10
  • 24

3 Answers3

2

You're trying to use the |-> operator inside a sequence, which is only allowed inside a property.

If rsp can only come one cycle after req, then this code should work:

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

The element after ##0 is there for debugging. You can omit it in production code.

I wouldn't mix assertions and coverage like this, though, as I've seen that the implication operators can cause issues with variable flow (i.e. lat won't get updated properly). You should have a property that just covers that you've seen a matching response after a request:

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);

Notice that I've used ##1 to separate the request from the response.

Tudor Timi
  • 7,453
  • 1
  • 24
  • 53
0

Basically your idea is right , But looks like the right hand side of the sequence will be evaluated once when the condition is true and hence the lat will be incremented only once .

You will need a loop mechanism to count the latency.

Below is an sample working example. You can change [1:$], ##1 etc based on how close the signals are generated

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);
Rahul Menon
  • 792
  • 7
  • 12
  • @RahulMnenon Your code is going to miss the case where the response comes immediately after the request (i.e. there is zero latency), because you require at least one cycle where you increment. – Tudor Timi Jun 26 '16 at 10:09
0

Alternatively...

property/sequences though they appear to be small code , in this case for every req ( which has not yet received a rsp ) a seperate process with its own counter is forked. This results in many counters doing very similar work. In case there are many req in flight ( and/or many instances of the property or sequence ) it will start adding into simulation run-time [ even though this is just a small block of code ]

so another approach is to keep the trigger simpler and we try to keep the processing linear.

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);

The above property is triggered only when req/rsp is seen and only 1 thread is active looking for it. If needed extra checks can be added into the function , But for latency counting this should be fine.

Anecdote :

Mentor AE - Dan discovered an assertion which was slowing our simulations by as much as 40 % . The poorly written assertion was part of our block tb and its effects went unnoticed there , as our block level test, run times were limited. It then sneaked into our top-level tb causing untold runtime losses till it was discovered a year later :) . [ guess we should have profiled our simulation runs earlier ]

Say for example if the above protocol implemented an abort at a later time, then the req-rsp thread will continue to process and wait ( till the simulation ends) for an aborted transaction , though it will not affect the functionality , it will sneakily continue to hog processor resources doing nothing useful in return. Till finally an vendor AE steps in to save the day :)

Rahul Menon
  • 792
  • 7
  • 12