Subroutine Call in SVA

A recent thread invoked interest about subroutine calls from sequence / property .

I went through LRM Section 16.11 to get a better grasp on the topic and tried the following :: edaplayground

Have noted a small list of doubts for which suggestions would be appreciated .

(1) Displays reporting value of v :: Sequence s1 executes once the consequent starts evaluation i.e from time 35 .
From T : 35 onwards , on every posedge of clk I would observe the value of v till the sequence s1 completes

 Why  is  that  we  observe  display  reporting  value  of  v  at  time 5 , 15 , 25 ? . ( Consequent  ' s1 ' hasn't  started  evaluation  yet )

(2) Variable e gets incremented in NBA region but assertion is evaluated in Observed region using values sampled in preponed region.

Hence  v  gets  assigned  the  preponed  value  of  e  (  i.e  updated  value  of  e isn't  assigned  ) . 

Please  correct  me  if  wrong . 

(3) LRM says ::

  • All subroutine calls attached to a sequence are executed at every end point of the sequence. For each end
    point, the attached calls are executed in the order they appear in the list.

  • Assertion evaluation does not wait on or receive data back from any attached subroutine.
    The subroutines are scheduled in the Reactive region, like an action block.

    (a) Does this mean the display at the end of the sequence executes ( in observed region ) before the display in subroutine ( which executes in Reactive Region ) ?

The last display report shows correct value of automatic variable w whereas value of f is at default 0 i.e it’s preponed value

(b) What does " at every end point of the sequence " mean ?

 The  endpoint  of  the  sequence  could  be  after  a few / many  clock  cycles  whereas  the  subroutine  call could  be  at  the  start  of  the  sequence . 
 Would  the  subroutine  be  called  that  later  on  ?

(c) Need some clarification regarding ::

" Assertion evaluation does not wait on or receive data back from any attached subroutine"
Does this apply only when task gets called through sequence / property ?
i.e any delays within the task doesn’t cause the assertion to be delayed .

(4) Is there an predefined order of execution between the $display is action blocks v/s the $display reported in subroutine ?

    (  As  both  execute  in  Reactive  region )

In reply to Have_A_Doubt:

Why is that we observe display reporting value of v at time 5 , 15 , 25 ? . ( Consequent ’ s1 ’ hasn’t started evaluation yet )

I updated the $display to include the value of “a” Edit code - EDA Playground


property  p1 ; @( posedge clk )  $rose( a ) |=>  s1 ;  endproperty  
assert property( p1 )  $display(" a=%b, Assertion  passed  at  %2t " , $sampled(a), $realtime ) ;
// simulation 
#KERNEL:  a=0, Assertion  passed  at   5 
// THE ASSERTION IS VACUOUSLY TRUE, thus the PASS action block is initiated. 
# KERNEL: TIME:15  v  is  1 
# KERNEL:  a=0, Assertion  passed  at  15 
# KERNEL: TIME:25  v  is  2 
# KERNEL: TIME:35  v  is  3 
# KERNEL: TIME:35  v  is  3 
# KERNEL:  a=0, Assertion  passed  at  35 
# KERNEL
  

You can use the assertion controls to suppress the VACUOUS pass action block.
I address this in my book in 4.2.4.1 Assert control.
$assertcontrol ( control_type [ , [ assertion_type ] [ , [ directive_type ] [ , [ levels ] [ , list_of_scopes_or_assertions ] ] ] ] ) ;
See below for examples

Hence v gets assigned the preponed value of e ( i.e updated value of e isn’t assigned ) .

Yes, correct.

Does this mean the display at the end of the sequence executes ( in observed region ) before the display in subroutine ( which executes in Reactive Region )

YES

What does " at every end point of the sequence " mean ?

Looking at the syntax

sequence_expr ::= ... 
| ( sequence_expr {, sequence_match_item} ) [ sequence_abbrev ] ... 
sequence_match_item ::= operator_assignment | inc_or_dec_expression | subroutine_call 
// Example:  
sequence s1; logic v, w; (a, v = e) ##1
   (b[->1], w = f, $display("b after a with v = %h, w = %h\n", v, w));
endsequence 
// The $display will occur at the end point of the sequence b[->1].
// I don't know why it says ät every end point.  Maybe because if you have something like
(a, v = e) ##1
   (b[*1:3], w = f, $display("b after a with v = %h, w = %h\n", v, w));
// then the subroutine $display wil fire for b[*1, b[*2], b[*3]

Assertion evaluation does not wait on or receive data back from any attached subroutine

Consider this example:


sequence s2; a ##1(1, f(c)); endsequence
sequence s3; bit v; a ##1(1, v=f(c)); endsequence
// Assertion that uses s2 or s3 is not affected by the results of the function call f(c).
 

Is there an predefined order of execution between the $display is action blocks v/s the $display reported in subroutine ?
( As both execute in Reactive region )

Probably not.

The following code declares some constants to make the controls more readable.


module test;
    logic clk, a, b, c, d;
    event start_sim; 
    int count1=0, count2=0; 
// now define lets to make the code more readable
    let LOCK = 1;
    let UNLOCK = 2;
    let ON = 3;
    let OFF = 4;
    let KILL = 5;
    let CONCURRENT = 1;
    let S_IMMEDIATE = 2; // simple immediate
    let D_IMMEDIATE = 12; // Final and Observed deferred immediate
    let EXPECT = 16;
    let ASSERT = 1;
    let COVER = 2;
    let ASSUME = 4;
    let ALL_DIRECTIVES = (ASSERT|COVER|ASSUME);
    let ALL_ASSERTS = (CONCURRENT|S_IMMEDIATE|D_IMMEDIATE|EXPECT);
    let VACUOUSOFF = 11;
    a1: assert property (@(posedge clk) a |=> b) $info("assert passed");
    else $error("assert failed");
    c1: cover property (@(posedge clk) a ##1 b);
    always @(posedge clk) begin
        ia1: assert (a);
    end
    always_comb begin
        if (c)
        df1: assert #0 (d);
    end
    function automatic void pass();
        $display("ap1 pass"); 
    endfunction : pass
    function automatic void fail();
        $display("ap1 fail"); 
    endfunction : fail
    ap1: assert property(@ (posedge clk) 
        a |-> b) pass(); else fail();

    initial begin
// the following systasks affect the whole design so no modules
// are specified
// disable vacuous pass action for all the concurrent asserts,
// covers and assumes in the design. Also disable vacuous pass
// action for expect statements.
    $assertcontrol(VACUOUSOFF, CONCURRENT | EXPECT);
// disable concurrent and immediate asserts and covers.
// The following systask does not affect expect
// statements as control type is Off.
    $assertcontrol(OFF); // using default values of all the
// arguments after first argument
// After 20 time units, enable assertions.
// explicitly specifying second, third and fourth arguments
// in the following task call
    #20 $assertcontrol(ON, CONCURRENT|S_IMMEDIATE|D_IMMEDIATE,
    ASSERT|COVER|ASSUME, 0);
// kill currently executing concurrent assertions after
// 100 time units but do not kill concurrent covers/assumes
// and immediate/deferred asserts/covers/assumes
// using appropriate values of second and third arguments
    #100 $assertcontrol(KILL, CONCURRENT, ASSERT, 0);
// the following assertion control task does not have any effect as
// directive_type is assert but it has selected cover directive c1
    #10 $assertcontrol(ON, CONCURRENT|S_IMMEDIATE|D_IMMEDIATE, ASSERT, 0, c1);
// now, after 10 time units, enable all the assertions except a1.
// To accomplish this, first we�ll lock a1 and then we�ll enable all
// the assertions and then unlock a1 as we want future assertion
// control tasks to affect a1.
    #10 $assertcontrol(LOCK, ALL_ASSERTS, ALL_DIRECTIVES, 0, a1);
    $assertcontrol(ON); // enable all the assertions except a1
    $assertcontrol(UNLOCK, ALL_ASSERTS, ALL_DIRECTIVES, 0, a1);
    if(!obj.randomize()) 
        `uvm_error("run_phase", "seq randomization failure"); 
end
 ap_x1: assert property(Px1) count1 <= count1 + 1'b1; // pass action block increments variable 
 ap_x2: assert property(Px1) count2 <= count2 + 1'b1; // pass action block increments variable 
initial begin
    $assertcontrol(KILL);
    wait (start_sim); 
    $assertcontrol(ON);
    // Optional if pass action does not update 
    $assertcontrol(LOCK, ALL_ASSERTS, ALL_DIRECTIVES, 0, ap_x1, ap_x2);
    $assertcontrol(PASSOFF);
    $assertcontrol(UNLOCK, ALL_ASSERTS, ALL_DIRECTIVES, 0, ap_x1, ap_x2);
    if (!req.randomize()) `uvm_error("MYERR", "This is a randomize error");
end
endmodule

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
** SVA Handbook 4th Edition, 2016 ISBN 978-1518681448

  1. SVA Package: Dynamic and range delays and repeats SVA: Package for dynamic and range delays and repeats - SystemVerilog - Verification Academy
  2. Free books: * Component Design by Example https://rb.gy/9tcbhl
  1. Papers:

Udemy courses by Srinivasan Venkataramanan (http://cvcblr.com/home.html)
https://www.udemy.com/course/sva-basic/
https://www.udemy.com/course/sv-pre-uvm/

In reply to ben@SystemVerilog.us:

Ben a few more things I would like to discuss

(1)

Does this mean the display at the end of the sequence executes ( in observed region ) before the display in subroutine ( which executes in Reactive Region ) ?

How is that display report the value of w correctly i.e value returned by ’ func ’ ?

Although func is called and returns in reactive region and $display executes in observed region , the correct value of w is reported .

(2)

Assertion evaluation does not wait on or receive data back from any attached subroutine

I  tried  2  codes  :: 

CODE1 uses the sequences s2 and s3 that you defined

CODE2 calls task from sequence

(a) Regarding CODE1 , the assertion passes at Next clock edge of ’ b ’ OR ’ c ’ being True i.e it does wait for 1 clock delay

i.e Although the subroutine is attached with 1 ( always True ) , the assertion does call the subroutine and conclude it as pass .

(b) Regarding CODE2 , the assertion doesn’t wait for the delay in task to complete before evaluating ’ c ’ .

 i.e  **' c '  is  evaluated  at  the  Next  clock  of  calling  the  task .**

Can a task called from sequence return a value to assign to local variable in sequence ?

return expression is illegal within task , but can user define task to have output argument direction ?

In reply to Have_A_Doubt:

In reply to ben@SystemVerilog.us:
(1)

YES

How is that display report the value of w correctly i.e value returned by ’ func ’ ?

Edit code - EDA Playground // my update


function automatic  int  func (  int i ) ;
    int  j ;  //  Automatic  by  default    
     f = e ;  // Should change to f= $sampled(e);
     j = f ;      
$display("TIME:%2t Within  func , i is %0d , f is %0d " , $time , i , f );  
     return j ;    endfunction
 // [Ben] **** NOTE **********
//  the display at the end of the sequence executes ( in observed region ) 
//  This is AFTER the NBA region that updates the value of e
//  THUS, in the function, f=e gets the incremented value of e
// and not the sampled value of e. 

  sequence  s1 ;   int v , w ;  @( posedge clk )  
    (1, v = e , $display("TIME:%2t  v  is  %0d " , $time , v ) )
    ##1 ( b[->1] , w = func(v) )                                            
    ##0( 1 , $display("TIME:%2t Sequence s1 Completes  with  b=%b, v == %0d , w == %0d , f == %0d " , $time , b, v , w , f) ) ;     endsequence
  property  p1 ; @( posedge clk )  $rose( a ) |=>  s1 ;  endproperty    
  assert property( p1 )  $display(" a=%b, Assertion  passed  at  %2t " , $sampled(a), $realtime ) ;
// How  is  that  display  report  **the  value  of  w   correctly
// [Ben] it is NOT what you expected. 
// function should have used f= $sampled(e);

# TIME:75  v  is  7 
# TIME:75 Sequence s1 Completes  with  b=1, v == 6 , w == 8 , f == 0 
# TIME:75 Sequence s1 Completes  with  b=1, v == 5 , w == 8 , f == 0 
# TIME:75 Sequence s1 Completes  with  b=1, v == 4 , w == 8 , f == 0 
# TIME:75 Sequence s1 Completes  with  b=1, v == 3 , w == 8 , f == 0 
# TIME:75 Sequence s1 Completes  with  b=1, v == 2 , w == 8 , f == 0 
# TIME:75 Sequence s1 Completes  with  b=1, v == 1 , w == 8 , f == 0 
# TIME:75 Sequence s1 Completes  with  b=1, v == 0 , w == 8 , f == 0 

Although [b]func is called and returns in reactive region** and $display executes in observed region , the correct value of w is reported .

[Ben] w should be 7 not 8

(2)
I tried 2 codes ::

CODE1 uses the sequences s2 and s3 that you defined

CODE2 calls task from sequence
(a) Regarding CODE1 , the assertion passes at Next clock edge of ’ b ’ OR ’ c ’ being True i.e it does wait for 1 clock delay
i.e Although the subroutine is attached with 1 ( always True ) , the assertion does call the subroutine and conclude it as pass .
(b) Regarding CODE2 , the assertion doesn’t wait for the delay in task to complete before evaluating ’ c ’ .
i.e ’ c ’ is evaluated at the Next clock of calling the task .
Can a task called from sequence return a value to assign to local variable in sequence ?
return expression is illegal within task , but can user define task to have output argument direction ?

From the sequence_match_item you can call a task or a function.
Only functions can return a value; tasks do not.