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

I read the following quote from Section 16.11 of the LRM

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

The first part of the quote is clear via the following sample code

   task  automatic  t1 ( int ip );
      #25 ;
      $display("At T:%2t task t1 completes with ip == %0d",$time,ip);
   endtask

   sequence s2;  //  Inherits  Clocking  Edge  from  property  'p2 '  !!
     (1, t1(d)) ##1  c ; 
   endsequence

   property p1 ;
     @(posedge clk) $rose(a) |=> s2 ;
   endproperty

   assert property( p1 ) ;

Evaluation of ‘c’ doesn’t wait for task ‘t1’ to complete.
‘c’ gets evaluated 2 clocks after $rose(a) is true ( irrespective of the delay within the task )

However I am not clear on the latter part ::

Assertion evaluation does not receive data back from any attached subroutine

If I were to write

 function int functn();
    return ( <expression_based_on_module_level_variables> );
 endfunction

  property p2 ;
     int  l1;
     @(posedge clk) $rose(a) |=> (1, l1 = functn() ) ##0 ( l1 inside {['hF0:'hFF]} );
   endproperty

   assert property( p2 ) ;

Here local variable ‘l1’ does receive data from subroutine ‘functn’ and only then using the returned value the expression ( l1 inside {['hF0:'hFF]} ) is evaluated.

So what does the latter part of the quote mean ?

Section 16.11 starts by saying

Tasks, task methods, void functions, void function methods, and system tasks can be called at the end of a successful nonempty match of a sequence.

Those are the subroutines that get scheduled to execute in the reactive region.

Your function functn is a non-void function. It gets evaluated as part of the expression it appears in.

Thanks Dave.
Assertion evaluation does not receive data back from any attached subroutine
where the subroutine is defined as
Tasks, task methods, void functions, void function methods, and system tasks can be called at the end of a successful nonempty match of a sequence.

Since neither of these ( subroutine ) can essentially return a value ( output arguments are illegal ) and assertion evaluation takes place in observed region ( subroutine execute in reactive region ) ,
LRM has the above quote

Hi Dave,
Seeking your comments on the following two examples

(1) I am using a modified code from LRM section 16.11 :: edalink1.
I am aware that ‘func’ executes in Observed region while the $display() which executes in Reactive region.
Why do we observe value of ‘f’ as 0 instead of 8 ( i.e the value assigned within ‘func’ ) ?

(2) I am using an immediate assertion within a task aka subroutine :: edalink2
Task ‘delay’ executes in reactive region whereas the event @(posedge clk) executes in active region.

(a) So once repeat(count) @(posedge clk); completes would we be in active region or reactive region ( since ‘delay’ essentially executes in reactive region ) ?

(b) In which SV region would the immediate assertion execute ?
If it’s in reactive region then it would see the NBA updated value of ‘b’ as 3 , if it’s in active region we would see the value of ‘b’ as 2 ( since NBA region is yet to occur )
I observe that the output differs across tools.

It would help if you showed us the code here instead of a link to it. Have you changed it since posting this? What is ‘f’?

A simple immediate assertion executes in whatever region the procedure code that it appears in is executing.

A task or function executes in the reactive region upon the match of a sequence. Once created, a procedure thread of execution cannot change its region.

 bit clk , a , b ; 
 int e , f ;  
 always  #5  clk  =  !clk ;
  
 always @( posedge clk ) e <=  e + 1 ;  //  Assignment  in  NBA  Region   
  
  function  int  func (int i);        
     f = e;         // Module scope variable assigned within the subroutine   
     $display("T:%2t Within  func , i is %0d , f is %0d",$time,i,f );    
     return f;   
  endfunction
  
  sequence  s1 ;
    int v , w ;
    @(posedge clk)      
    ( 1 , v = e , $display("T:%2t v == %0d",$time,v) )  ##1 ( b[->1] , w = func(v) , $display("T:%2t Sequence s1 Completes  with  v == %0d , w == %0d , f == %0d",$time,v,w,f ) ) ;       
  endsequence
  
  property  p1 ;    
    @(posedge clk)  $rose(a) |=> s1;   
  endproperty 

  assert property(p1)  $display("Assertion  passed  at  T:%2t",$time) ;
  
  initial  begin  
   #24 ; a = 1 ;   
   #10 ; a = 0 ;  //  T: 34
   #40 ; b = 1 ;  //  T: 74
   #10 ; b = 0 ;  //  T: 84
    #2 ; $finish();    
  end  

Although ‘f’ is assigned 8 ( in observed region ), why do we observe it’s value as 0 via the $display which executes in reactive region i.e after the assignment to ‘f’ ?

  bit clk , a , b ;  
  always #5 clk = !clk;
  int val = 2;

  always @(posedge clk) b <= b  + 1; // Updated in NBA region
  
  task automatic delay( int count );  
    $display("Task called at T:%0t with i/p arg == %0d",$time,count);
    if( count > 0 ) begin      
      repeat(count) @(posedge clk);
      $display("Task completes at T:%0t",$time);
    end
    
    // Immediate assertion
    im: assert ( b == 2) $display("Immediate assertion passes");  // Question about this
                    else $display("Immediate assertion fails");
  endtask
  
  property p1;       
    @(posedge clk) $rose(a) |-> (1, delay(val));
  endproperty
  
  assert property(p1);
  
  initial begin   
    #04 ; a = 1 ;
    #25 ; $finish();    
  end  

Although ‘delay’ executes in reactive region, due to repeat(count) @(posedge clk); would it re-enter active region ( via loopback from reactive ) due to the event control ?

On unblocking the next procedural statement is the immediate assertion.
So would the immediate assertion execute in reactive region ( since ‘delay’ executes in reactive region ) OR would it execute in active region itself ( since event control executes in active region ) ?

Does this mean that the immediate assertion executes in reactive region ( same as the subroutine ) ?

This is because when calling a subroutime on the match of a sequence:

Actual argument expressions that are passed by value use sampled values of the underlying variables and are consistent with the variable values used to evaluate the sequence match.

The $display statement inside func is not going to use the sampled value.

Event controls resume in the same region where they were encountered to suspend the process. The construct that creates a process determines which region it executes in. This means the same task can be used in two different regions.

Hi Dave,
A few follow-up questions
(1) I am trying to decipher your last quote

Event controls resume in the same region where they were encountered to suspend the process. The construct that creates a process determines which region it executes in.

(a) So repeat(2) @(posedge clk) within the subroutine would resume i.e unblock in reactive region ( as ‘delay’ executes in reactive region ) ? ( my understanding was event control always unblocks in active region )

(b) I am not clear on the last line

This means the same task can be used in two different regions.

(c) Since the subroutine executes in reactive region, the immediate assertion ( following repeat(2) @(posedge clk); ) would execute in reactive region as well, correct ?
i.e the Immediate assertion would use the value of ‘b’ as 3 ( the updated NBA value at time 25 units )

(2) Within sequence ‘s1’ in above code,
on match of b[->1] at time 75 units, first the non-void function ‘func’ executes in observed region where it assigns ‘f’ as 8 , executes $display("T:%2t Within func … ) and returns value of 8 which is assigned to local variable ‘w’.
Then the system task ( $display(“T:%2t Sequence s1 Completes … , f == %0d”,$time,v,w,f ) executes in reactive region.
Why is it that we observe value of ‘f’ as 0 via the $display and not the updated value of 8 within ‘func’ ?
Is it because argument ‘f’ within the $display uses it’s sampled value ( i.e pre-poned value of 0 ) ?