Using sequence as event contol

Hi,
I was trying a sequence as an event control: edalink

Tasks and void function get called in Reactive region whereas the event control ’ @(seq) ’ unblocks in loopback/feedback from Observed to Active region.
So when @(seq) unblocks what should the value of length be ? Should we observe the value assigned from subroutine ?
Is there a pre-defined order of execution between the assignment within the subroutine and unblocking of event control @(seq) ?

I checked **LRM Figure 4-1—Event scheduling regions:
There is a loopback from Observed region to Active region and another loopback from Re-NBA to Active region.

Note: There is no direct loopback from Reactive to Active region.**

In reply to MICRO_91:
I modified your code slightly and added varivle f that toggles.
code: Sequence as Event control(1) - EDA Playground
wave: EPWave Waveform Viewer
SIM: T:35 Length == 0 f=0
All signals change at the clock edge in the Active region
At t35, $sampled(c)==1 and $sampled(len)==0
Thus, at t35 ##0 (1, data = len , Length( data )
Also, at t35, in the Observed region, the end point of seq is true.
Thus, always@( seq )
$display(“T:%0t Length == %0d f=%d”,$time,length, f);
Length==0 (as explained above)
$sampled(f) at the posedge clk is 1, but it changed in the Active region to 0
The $display of f is the value of f in the Observed Region, which is a 0
(this is what is sees with $display what you see NOW)
NOTE: If I change the code to
always@( seq )
$display(“T:%0t Length == %0d f=%d”,$time,length, $sampled(f));
Sequence as Event control(2) - EDA Playground
I get T:35 Length == 0 f=1


module top;
  
  bit clk , a , b , c, f ;
  
  bit [3:0] length , len ;
  
  always #5 clk = !clk;
  
  function void Length( input bit [3:0] L );
    length = L;
  endfunction
  
  sequence seq;
    bit [3:0] data;
    @(posedge clk) a ##1 b ##1 c ##0 (1, data = len , Length( data ) );  
  endsequence
  
  always@( seq )
    $display("T:%0t Length == %0d  f=%d",$time,length, f);
  
  always @(posedge clk) f<=!f;
    
  initial begin
     $dumpfile("dump.vcd"); $dumpvars;
     #5 ; a = 1 ;
    #10 ; a = 0 ; b = 1 ;
    #10 ; b = 0 ; c = 1 ; 
    #10 len = 10 ;
    #10 ;
    #2; $finish();
  end  
  
endmodule 

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

or Cohen_Links_to_papers_books - Google Docs

Getting started with verification with SystemVerilog

In reply to ben@SystemVerilog.us:

Hi Ben,

  1. In your code the variable ‘f’ is updated in NBA region whereas the endpoint of sequence ‘seq’ occurs in Observed region.
    At T:35 by Observed region the value of ‘f’ would be updated to 0.

    Event control @(seq) unblocks in loopback from Observed to Active region and the $display() within it executes in Active region.
    Hence we observe updated value of 0 for ‘f’.

  2. In your code variable ‘length’ is assigned preponed value of 0 ( which is same as default value ) so there is no discrepancy here
    i.e whether the assignment occurs before or after @(seq) unblocks.
    In both cases the value (0) is the same

In my code the void function ‘Length’ is assigned value of 10 in Reactive region whereas @(seq) unblocks in loopback from Observed to Active region.

So some tools show updated value for Length whereas some show the non-updated value of Length.

**As the void function is called in Reactive region the assignment also occurs in Reactive region whereas the seq. endpoint occurs in Observed region.
When do we say that the sequence has ended ? i.e after the assignment is done for ‘Length’ OR before the assignment as soon as ‘c’ is true
**

In reply to MICRO_91:

In reply to ben@SystemVerilog.us:
In my code the void function ‘Length’ is assigned value of 10 in Reactive region whereas @(seq) unblocks in loopback from Observed to Active region.

Your code " … ##0 (1, data = len , Length( data )
The Reactive region is for Action block.
See my paper on immediate assertions (link in the list of papers)

[/quote][b]As the void function is called in Reactive region …
[/quote[
Again, the function is called in a sequence matched item in the Observed region.

In reply to ben@SystemVerilog.us:

Ben,

Again, the function is called in a sequence matched item in the Observed region.

As per our discussion a few months ago, we both concluded that a void function/task called as part of sequence_match_item executes in Reactive region similar to action block.

I am currently referring to your 2nd reply in this thread

LRM Section 16.11 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.

As the 1st line of the above LRM quote says:
“All subroutine calls attached to a sequence are executed at every end point of the sequence.”

So now we have @(seq) which unblocks at every endpoint of sequence as well as the subroutine call which too executes at every endpoint of sequence

Possibly a race condition ? OR
If I go by Figure 4-1 of the LRM the loopback from Observed region to Active region occurs before loopback from Re-NBA to Active.
So should @(seq) unblock before the subroutine gets called in Reactive region ?

In reply to MICRO_91:

In reply to ben@SystemVerilog.us:
Ben,
As per our discussion a few months ago, we both concluded that a void function/task called as part of sequence_match_item executes in Reactive region similar to action block.

NO, that is only true for action blocks.
LRM Section 16.11 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.
[Ben] Moving into another topic
Assertion evaluation does not wait on or receive data back from any attached subroutine.
The subroutines are scheduled in theReactive region,like an action block.

[Ben] thus, " … ##0 (1, data = len , Length( data ), which causes the variable length to be modified, does not affect the assertion evaluation.
length is modified in the Observed region.

A side comment, module variables modified in an assertion should be used only for support logic. A user should be concerned with these timing regions/
Ben

In reply to ben@SystemVerilog.us:

Ben,
Unfortunately I am still not clear on the following

(1)

LRM Section 16.11 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.

This tells me that local_variable 'data' is assigned before calling function 'Length'
In cases where there are multiple sequence_match_items, they would execute in left to right order.

(2)

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

We discussed this LRM quote in [this](https://verificationacademy.com/forums/systemverilog/achieving-dynamic-delays-sva-using-subroutine). So when a time consuming task gets called as part of sequence_match_item, the assertion doesn't wait for the task to complete

(3)

The subroutines are scheduled in the Reactive region,like an action block

So doesn't this mean that void function 'Length' gets called in Reactive region ?
As void function/task don't return any value , they execute in Reactive region.

As the void function 'Length' gets called in Reactive region the assignment within it would also execute in Reactive region right ?

(4)

A side comment, module variables modified in an assertion should be used only for support logic. A user should be concerned with these timing regions

 I do agree but consider a code where the sequence event control is used as triggering event to a covergroup,
 And the coverpoint is sampling the value of variable assigned in subroutine.

 The same scenario would exist i.e would the value prior to assignment would be sampled OR will the updated value be sampled ?

In reply to MICRO_91:

The way I think it works is that functions called in a sequence_matchedItem
are scheduled in the Observed region. If the function returns a value, it is executed immediately. Thus,

function bit f(bit i) return !i; endfunction
property p;
  bit x; 
  (a, x=f(c)) ## d==x ..; // x is updated in the Observed region
// Otherwise you could not complete the sequence
..
function void Length( input bit [3:0] L ); length = L;  endfunction
task t(bit [3:0] L ); length = L; endtask
assert property( @(ce) (a, Length(data), t(data1)) ); 
// The function and the task are scheduled to be processed in the Observed region. 
// When are they executed? Probably after all executions of queued up 
// assertions are completed, thus probably in the Reactive region. 
// But it really doesn't make a difference to the user. 
// Any updated module variables is not seen by any ongoing assertions 
// being executed in that time step since signals are sampled. 


Ben

In reply to ben@SystemVerilog.us:

The way I think it works is that functions called in a sequence_matchedItem
are scheduled in the Observed region. If the function returns a value, it is executed immediately. Thus,
function bit f(bit i) return !i; endfunction
property p;
bit x;
(a, x=f(c)) ## d==x …; // x is updated in the Observed region
// Otherwise you could not complete the sequence

I agree. The same is confirmed in LRM.


LRM 16.10  Local variables :
Initialization assignments shall be performed in the Observed region in the order that they appear in the sequence or property declaration.

The sequence or property shall assign a value to the local variable prior to the point at which the reference is made.

As ‘x’ will be assigned in observed region, function ‘f’ executes in Observed region as well.
( Hence I believe functions with return type (i.e non-void functions) called as part of sequence_match_item execute in Observed region )

  1. Regarding the order of execution between the assignment within the subroutine and execution of action block,

(a) LRM 16.11 Calling subroutines on match of a sequence :

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.

Hence can I state the following ?

Since both void function/task as well as action blocks execute in Reactive region, there is no pre-defined order of execution between the two

In the code, assignment to ‘length’ within void function ‘Length’ as well as $display within action block execute in Reactive region.
As a result there is no pre-defined order of execution between the function ‘Length’ and action block.

In reply to MICRO_91:

As a result there is no pre-defined order of execution between the function ‘Length’ and action block.

Probably correct. However, since the void function length was put into q queue to be executed at a later point, anything to be queued in the action block may be executed next.
A tool vendor can do what he wants.

In reply to ben@SystemVerilog.us:

Hi Ben,
A final question to conclude the discussion.

Consider the following code: edalink1

As @(seq) unblocks in loopback from Observed to Active region, the $display() within always@(seq) executes before $display() in action block ( which executes in Reactive region )
So this essentially tells us that loopback from Observed to Active occurs before Reactive region.

Now consider the code at the top of this thread: edalink2

The void function executes in Reactive region similar to action block ( as we discussed in the last 2 replies ).

Hence the $display() within always@(seq) executes before void function ‘Length’ executes.
Therefore I believe ‘length’ would be unassigned when $display() executes within always@(seq).

Would like to hear on your thoughts on this.

In reply to MICRO_91:
Q: In which region a void function or task is executed if that function/task is called from a sequence_match_item?
My previous answer may be incorrect as it may be tool-dependent.
**Previous answer:**The void functions and tasks are scheduled to be processed in the Observed region. When are they executed? Probably after all executions of queued-up
assertions are completed, thus probably in the Reactive region.
However, when I tested this model, it appeared that some tools(not all) execute the void functions and tasks when they are called in the Observed region. Thus, if the task has Delays or wait statements that would not work in completing an on-going assertion. The tool may then set a warning about the non-support of Delays or wait statements in match item task calls.


module m; 
    `include "uvm_macros.svh"   import uvm_pkg::*;
    bit a, b, c, dbg, clk; 
    initial forever clk = #1 !clk;
    task automatic t1(); dbg <=1; @(negedge clk) dbg<=0; endtask 
    sequence s_ab; @(posedge clk) a ##1 b; endsequence 
    ap_abc: assert property(@ (posedge clk) (s_ab.triggered, t1()) |-> ##2 c);  
     ...
    endmodule

To get around this issue, you could have another procedure to carry on the delays/additional clocking processes.


 task automatic t1(); dbg <=1;//  @(negedge clk) dbg<=0; 
    endtask 
  always @(posedge dbg)  @(posedge clk)  dbg<=0; 

BTW, Tools seem to have no issue with delays if the task is in the action block

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

In reply to ben@SystemVerilog.us:

Previous answer:The void functions and tasks are scheduled to be processed in the Observed region. When are they executed? Probably after all executions of queued-up
assertions are completed, thus probably in the Reactive region.
However, when I tested this model, it appeared that some tools(not all) execute the void functions and tasks when they are called in the Observed region. Thus, if the task has Delays or wait statements that would not work in completing an on-going assertion.

I have a similar understanding on this.


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

Regarding working of blocking tasks called as sequence_match_item, we have discussed the same in detail: achieving-dynamic-delays-sva-using-subroutine