Difference in output using 'within' V/S 'intersect' operator

Hi All,
I was trying SVA for requirement: “In response to a request, grant must at received before/same clock as next request”

I tried solution using ‘within’ , ‘intersect’ operators : edalink.

However I notice that the output differs when there are 2 grants received for 1 request.
Using ‘intersect’ the assertion fails as soon as 2nd $rose(grant) is True , whereas using ‘within’ the assertion passes when 2nd request is received.

It seems the 2nd grant goes unnoticed for ‘within’,why is it so ?

Based on my understanding $rose(gnt)[=1] is equivalent to ( !rose(gnt)[*0:] ##1 $rose(gnt) ##1 !rose(gnt)[*0:] ) ,
so shouldn’t the ‘within’ operator also have failed at 2nd grant ? ( as $rose(gnt)[=1] is false )

In reply to MICRO_91:
within V/S intersect operator(1) - EDA Playground // code
EPWave Waveform Viewer // wave


 ap1:assert property( @(posedge clk)$rose(req) |=>  
                     $rose(gnt)[=1] intersect $rose(req)[->1]) 
                      pass1=pass1+1; else fail1=fail1+1; 
                                    
 ap2:assert property( @(posedge clk)  $rose(req) |=>  
                      $rose(gnt)[=1] within $rose(req)[->1])
                        pass2=pass2+1; else fail2=fail2+1; 
1)  (seq1 within seq2) is equivalent to: ((1[*0:$] ##1 seq1 ##1 1[*0:$]) intersect seq2 )
2)  $rose(gnt)[=1] is equivalent to !$rose(gnt)[*0:$] ##1 $rose(gnt) ##1 !$rose(gnt)[*0:$] ,
// expanding $rose(gnt)[=1] within $rose(req)[->1])
 (1[*0:$] 
   !$rose(gnt)[*0:$] ##1 $rose(gnt) ##1 !$rose(gnt)[*0:$] 
   ##1 1[*0:$])
   intersect $rose(req)[->1]
 // Consider the LHS of the intersect, this gets simplified to 
   (1[*0:$] !$rose(gnt)[*0:$] ##1 $rose(gnt) ##1 !$rose(gnt)[*0]] ##1 1[*0:$]) or // 1st
   (1[*0:$] !$rose(gnt)[*0:$] ##1 $rose(gnt) ##1 !$rose(gnt)[*1]] ##1 1[*0:$]) or  //2nd
   ..
   (1[*0:$] !$rose(gnt)[*0:$] ##1 $rose(gnt) ##1 !$rose(gnt)[*n]] ##1 1[*0:$]) or  //nth
  // We don't need the 2nd, ...nth. because the 1st of the ORed sequences is sufficient here  
  // consider the 1st 
   (1[*0:$] !$rose(gnt)[*0:$] ##1 $rose(gnt) ##1 !$rose(gnt)[*0]] ##1 1[*0:$])
   // get reduced to the following because of the [*0].  (a[*0] ##1 b) is reduced to (b)
   (1[*0:$] !$rose(gnt)[*0:$] ##1 $rose(gnt) ##1 1[*0:$])
   // THUS, the assertion does not test fora 2nd occurrence of $rose(gnt). 
   // a 2nd occurrence of $rose(gnt) does not cause a fail
   // For a pass, all we need here with the within is a single occurrence of $rose(gnt).

Ben Cohen
Ben@systemverilog.us
Link to the list of papers and books that I wrote, many are now donated.

or Links_to_papers_books - Google Docs

Getting started with verification with SystemVerilog

In reply to ben@SystemVerilog.us:

Thanks Ben.

(1) I was trying to use same logic (with different equivalent expression) for ‘intersect’ operator .
The consequent begins evaluation at time:35. 1st grant is true at time:85 and 2nd grant is true at time:125


 $rose(gnt)[=1] is equivalent to !$rose(gnt)[*0:$] ##1 $rose(gnt) ##1 !$rose(gnt)[*0:$] ,

 // Since !$rose(gnt) is true from t:35 to t:75, i.e !$rose(gnt)[*5] is true in our case
 // One of the possible LHS sequence is :
    ( !$rose(gnt)[*5] ##1 $rose(gnt) ##1 !$rose(gnt)[*0:$] )
//  Which can be further expanded to
    ( !$rose(gnt)[*5] ##1 $rose(gnt) ##1 !$rose(gnt)[*0] ) or  // 1st seq
    ( !$rose(gnt)[*5] ##1 $rose(gnt) ##1 !$rose(gnt)[*1] ) or
    ..................................................
    ( !$rose(gnt)[*5] ##1 $rose(gnt) ##1 !$rose(gnt)[*N] )

 //  1st  seq  has an empty sequence !$rose(gnt)[*0] , hence it can be re-written as 
    ( !$rose(gnt)[*5] ##1 $rose(gnt) ##0 `true )  // 1st seq

So why does assertion fail when 2nd grant is received ? Shouldn’t the single $rose(gnt) be sufficient for the LHS sequence to be a match ?

(2) In your equivalent expression I believe you have missed out on ##1


1)  (seq1 within seq2) is equivalent to: ((1[*0:$] ##1 seq1 ##1 1[*0:$]) intersect seq2 )
2)  $rose(gnt)[=1] is equivalent to !$rose(gnt)[*0:$] ##1 $rose(gnt) ##1 !$rose(gnt)[*0:$] ,

// expanding $rose(gnt)[=1] within $rose(req)[->1])
 (1[*0:$] ##1 !$rose(gnt)[*0:$] // ##1 added
   ##1 $rose(gnt) ##1 !$rose(gnt)[*0:$] ##1 1[*0:$]) intersect $rose(req)[->1]
    

In reply to MICRO_91:


ap1:assert property( @(posedge clk)$rose(req) |=>  
                     $rose(gnt)[=1] intersect $rose(req)[->1]) 
                      pass1=pass1+1; else fail1=fail1+1; 
//Assertion fails at t 122.5  when the 2bd gnt is seen.                                    
//  1st  seq  has an empty sequence !$rose(gnt)[*0] , hence it can be re-written as 
    ( !$rose(gnt)[*5] ##1 $rose(gnt) ##0 `true )  // 1st seq
// BUT for an intersect the thread of the 
//  LHS sequence must be of the same length as the tread of the RHS sequence
// Thus, for the "//1st seq" that would occur only if $rose(req)[->1] occurred in that cycle. 
// It did not in that sim.  Thus, you need to consider the other ORs
// One of the possible LHS sequence is :
    ( !$rose(gnt)[*5] ##1 $rose(gnt) ##1 !$rose(gnt)[*0:$] )
//  Which can be further expanded to
    ( !$rose(gnt)[*5] ##1 $rose(gnt) ##1 !$rose(gnt)[*0] ) or  // 1st seq NO INTERSECT yet
    ( !$rose(gnt)[*5] ##1 $rose(gnt) ##1 !$rose(gnt)[*1] ) or
    ..................................................
    ( !$rose(gnt)[*5] ##1 $rose(gnt) ##1 !$rose(gnt)[*N] )

Ben

In reply to ben@SystemVerilog.us:

Ben ,
A final question.

For an intersect operator to pass,LHS sequence must be of the same length as the RHS sequence

Using equivalent ‘or’ sequences for LHS, I am trying to understand what causes LHS sequence to be termed as ‘it ends’ at t:125 ?

In the stimulus :

  1. !$rose(gnt) is true from t:35 to t:75, i.e *!$rose(gnt)[5] is a match
  2. Next clock at time:85 $rose(gnt) is true i.e *!$rose(gnt)[5] ##1 $rose(gnt) is a match
  3. !$rose(gnt) is true from t:95 to t:115, i.e **!$rose(gnt)[5] ##1 $rose(gnt) ##1 !$rose(gnt)[3] is a match
  4. At time:125, $rose(gnt) is true for 2nd time

  //  In  the  equivalent 'or' expressions for LHS sequence :
 ( !$rose(gnt)[*5] ##1 $rose(gnt) ##1 !$rose(gnt)[*0] ) or  // 1st seq match but NO INTERSECT yet
 ( !$rose(gnt)[*5] ##1 $rose(gnt) ##1 !$rose(gnt)[*1] ) or  // 2nd seq match but NO INTERSECT at time:95
 ( !$rose(gnt)[*5] ##1 $rose(gnt) ##1 !$rose(gnt)[*2] ) or  // 3rd seq match but NO INTERSECT at time:105
 ( !$rose(gnt)[*5] ##1 $rose(gnt) ##1 !$rose(gnt)[*3] ) or  // 4th seq match but NO INTERSECT at time:115

  At time:125 when 2nd $rose(gnt) is true :
 ( !$rose(gnt)[*5] ##1 $rose(gnt) ##1 !$rose(gnt)[*4] ) or  // 5th seq doesn't match at time:125

 // Correspondingly all remaining sequences (6th to Nth) don't match due to 2nd $rose(gnt)

Due to 2nd $rose(gnt) at time:125, 5th to Nth sequences don’t match : *(!$rose(gnt)[5] ##1 $rose(gnt) ##1 !rose(gnt)[*4:])

Essentially 1st to 4th sequences matched but there was No intersect, remaining 5th to Nth sequences don’t match due to 2nd $rose(gnt).

So how is it interpreted as LHS sequence ends at time:125 ?

In reply to MICRO_91:
I am looking at this
within V/S intersect operator(1) - EDA Playground // code
EPWave Waveform Viewer // wave
For an intersect operator to pass,LHS sequence must be of the same length as the RHS sequence
Example


 a[=1] intersect b[->1]) // equivalent to, as you stated 
 !a[*0:$] ##1 a ##1!a[*0:$]  intersect  !b[*0:$] ##1 b //
// assume that the length of the sequence b[->1] is 5 cycles.(b==1 after 4 cycles from start)  
// the threads of the LHS that can only be in consideration are 
a[*1] ##1 !a[*4]
!a[*1] ##1 a ##1 !a[*3]
!a[*2] ##1 a ##1 !a[*2]
!a[*3] ##1 a ##1 !a[*1]
!a[*4] ##1 a 
// If the LHS is as follows
!a ##1 a ##1 !a ##1 a ##1 !a  // we have 2 occurrence of a 
// An optimized simulator would recognized that there is no need to further evaluate 
// the LHS since anything thread after (!a ##1 a ##1 !a ##1 a) is a no-match even if it 
// length-match the RHS.  This is because the LHS is a[=1].
// Thus, at the end of the thread of length 4 the simulator can declare a failure. 

within V/S intersect operator(2) - EDA Playground code
EPWave Waveform Viewer wave


// With code as shown in above link, replacing the intersect with "and" 
// causes a pass because the "and" does not require length-matching
ap1:assert property( @(posedge clk)$rose(req) |=>  
                     $rose(gnt)[=1] and $rose(req)[->1]) 
   //   $rose(gnt)[=1] intersect $rose(req)[->1]) 
                      pass1=pass1+1; else fail1=fail1+1; 

Ben Cohen
Ben@systemverilog.us
Link to the list of papers and books that I wrote, many are now donated.

or Links_to_papers_books - Google Docs

Getting started with verification with SystemVerilog

In reply to ben@SystemVerilog.us:

// An optimized simulator would recognized that there is no need to further evaluate
// the LHS since anything thread after (!a ##1 a ##1 !a ##1 a) is a no-match even if it
// length-match the RHS. This is because the LHS is a[=1].
// Thus, at the end of the thread of length 4 the simulator can declare a failure.

So as soon as 2nd $rose(gnt) is true, 5th and latter sequences don’t match .
Hence it’s interpreted as LHS sequence ends at time:125 resulting in assertion failure.

In reply to MICRO_91:

So as soon as 2nd $rose(gnt) is true, 5th and latter sequences don’t match .
Hence it’s interpreted as LHS sequence ends at time:125 resulting in assertion failure.

Yes. This is an optimization by the tool.

In reply to ben@SystemVerilog.us:

Hi Ben,
I wanted to know what is the correct SVA terminology for the following

  1. When assertion passes, do we say that the consequent is a match OR consequent is true ?
  2. When assertion passes, do we sat that intersect/within operator was true OR intersect/within operator was a match ?

In reply to Have_A_Doubt:

I wanted to know what is the correct SVA terminology for the following

  1. When assertion passes, do we say that the consequent is a match OR consequent is true ?

I address the terminologies in my paper, see link below.
When assertion passes, we say that the consequent as a sequence is a match,
but the consequent as a property is true, and the assertion passes or fails.

  1. When assertion passes, do we say that intersect/within operator was true OR intersect/within operator was a match ?
  1. When assertion passes, we say that the property with the intersect/within operator was true; also the sequence with the intersect/within operator was a match.



2 Reflections on Users’ Experiences with SVA, part 1

Important concepts on EXPRESSING REQUIREMENTS,
Terminology, threads in ranges and repeats in antecedents, multiple antecedents.
---- From above link
Terminology
Before getting into the topic of threads, a review of key terms when addressing SVA sequences, properties, and assertions is necessary because these terms are often misused. Let’s “speak” SVA using proper words and grammar:

Match: A sequence is either matched or non-matched; that’s it! It is not addressed as pass/success/fail/true/false, though many users consider a match a pass.

True/False: A property is either true or false. There is also the concept of vacuity, and a vacuously true property is considered ‘true’ in the sense that it is not ‘false’. Consider the following property that has three property threads: a ##[1:3] b |-> c. For this property to succeed, we need at least one thread to succeed nonvacuously and no thread to fail. Thus, there can be vacuously true threads.

Pass/Fail/Active: An assertion either passes or fails or is active (i.e., not yet completed with a determination of its fate). There are two types of “passes”: vacuous pass and nonvacuous pass. Nonvacuous passes are typically counted by tools and can thus be considered covered. A sequence that is interpreted as a property is never vacuous.

Covered: A property/sequence/expression is considered covered if it passes nonvacuously with the cover property, cover sequence, or cover statements. A covered property is evaluated as strong. Tools provide statistics on passed assertions and assumptions, which can be counted as covered.

Thread: A thread is a search path for the property’s success within an evaluation attempt that starts at the leading clocking event of the property. For example, a bus request that is acknowledged within 1 to 2 cycles has 2 threads: request followed by acknowledge in 1st cycle, or a request followed by acknowledge in 2nd cycles. A sequence is multi-threaded if it includes any of the following operators: and, intersect, or, range delay (e.g., ##[1:3] a), consecutive range repetition (e.g., a[*1:3]), and non-consecutive repetition (e.g., a[->1], a[=1]).

Attempt vs. thread: An attempt is a new evaluation of an assertion, and that assertion starts one or more threads. In some posts, I see people talk about attempts as threads interacting with each other; they don’t! The threads from each successful attempt are separate from other launched threads from other attempts.

For the assertion pass using ‘within’ I would like to add to Ben’s quote :

  1. (seq1 within seq2) is equivalent to: ((1[*0:] ##1 seq1 ##1 1[*0:]) intersect seq2 )
  1. $rose(gnt)[=1] is equivalent to !rose(gnt)[*0:] ##1 $rose(gnt) ##1 !rose(gnt)[*0:] ,
    // expanding $rose(gnt)[=1] within rose(req)[->1]) (1[*0:]
    !rose(gnt)[*0:] ##1 $rose(gnt) ##1 !rose(gnt)[*0:]
    ##1 1[*0:$])
    intersect rose(req)[->1] // Consider the LHS of the intersect, this gets simplified to (1[*0:] !rose(gnt)[*0:] ##1 $rose(gnt) ##1 !rose(gnt)[*0]] ##1 1[*0:]) or // 1st
    (1[*0:$] !rose(gnt)[*0:] ##1 $rose(gnt) ##1 !rose(gnt)[*1]] ##1 1[*0:]) or //2nd

    (1[*0:$] !rose(gnt)[*0:] ##1 $rose(gnt) ##1 !rose(gnt)[*n]] ##1 1[*0:]) or //nth
    // We don’t need the 2nd, …nth. because the 1st of the ORed sequences is sufficient here
    // consider the 1st
    (1[*0:$] !rose(gnt)[*0:] ##1 $rose(gnt) ##1 !rose(gnt)[*0]] ##1 1[*0:])
    // get reduced to the following because of the [*0]. (a[*0] ##1 b) is reduced to (b)
    (1[*0:$] !rose(gnt)[*0:] ##1 rose(gnt) ##1 1[*0:])
    // THUS, the assertion does not test fora 2nd occurrence of $rose(gnt).
    // a 2nd occurrence of $rose(gnt) does not cause a fail
    // For a pass, all we need here with the within is a single occurrence of $rose(gnt).

In the stimulus, consequent is evaluated from t:35.

  1. !$rose(gnt) is true from t:35 to t:75, i.e *!$rose(gnt)[5] is a match
  2. Next clock at time:85 $rose(gnt) is true i.e *!$rose(gnt)[5] ##1 $rose(gnt) is a match
  3. At time:145, $rose(req) is true for 2nd time. Hence RHS sequence ends at time:145

Out of the infinite 'or’ed equivalent sequences for LHS sequence,the following sequence matches as well as intersects :
**( 1[*0] ##1 !$rose(gnt)[*5] ##1 $rose(gnt) ##1 1[*6] ) i.e ( ##0 !$rose(gnt)[5] ##1 $rose(gnt) ##1 1[6] )

Since the above sequence intersects with RHS sequence: $rose(req)[->1], the assertion passes