Why does process::self() in static variable initialization function call return a process handle?

I have the following test code:

module test;
  function automatic bit check_process;
    if ( process::self() != null)
      $display("can get a process in static initializer!");
    return 0;
  endfunction
  
  bit x = check_process();
endmodule

In EDAPlayground all 4 simulators printed out “can get a process in static initializer!”.

Systemverilog initializes those variable before any initial or always procedures. Why does a process exists there ?

In reply to robert.liu:

This is an area where some tools have diverged from the LRM. According to the LRM section 9.5 Process execution threads, a static initialization does not create a process, nor does a continuous assignment. That is why section 13.4.4 Background processes spawned by function calls does not allow fork/join_none from anything but a process created by an initial or always block.

But there must be some kind process for executing static initializations. Some tool have lumped all of those initializations into a single process. Others have created a process for each initialization. The following code executes 4 different ways for each of the 4 simulators on EDAPlayground.

  function automatic bit check_process;
    static process previous;
    if ( process::self() != null) begin
      $display("can get a process in static initializer!");
      if (previous != process::self())
        $display("different self");
        end
    previous = process::self();
    return 0;
  endfunction
  bit x = check_process();
  bit y = check_process();
  bit z = check_process();
  wire w = check_process(); 
  
  initial #10 $display("The end");
  final x = check_process();
  final y = check_process();
endmodule

In reply to dave_59:

Thanks Dave. That’s interesting. New knowledge learnt here.

I changed the code to print clearer message:

module test;
  function automatic bit check_process(string prefix);
    static process previous;
    static bit previous_valid;
    if ( process::self() != null) begin
      $display(prefix, " can get a process in static initializer!");
      if (previous_valid && previous != process::self())
        $display(prefix, " different self");
    end
    previous = process::self();
    previous_valid = 1;
    return 0;
  endfunction
  bit x = check_process("bit x");
  bit y = check_process("bit y");
  bit z = check_process("bit z");
  wire w0 = check_process("wire w0"); 
  wire w1 = check_process("wire w1"); 
 
  initial #10 $display("The end");
  final x = check_process("final x");
  final y = check_process("final y");
endmodule