task automatic sub1( int ip1 , ref int ip2 );
$display("ip1 == %0d",ip1);
$display("ip2 == %0d",ip2);
$display("a == %0d\n",a);
endtask
... @(posedge clk) (1,sub1(a,a));
1800'2023 13.5.2 Pass by reference
Arguments passed by reference are not copied into the subroutine area,
rather, a reference to the original argument is passed to the subroutine.
...
When the argument is passed by reference, both the caller and the subroutine
share the same representation of the argument; therefore, any changes made to the argument,
within either the caller or the subroutine, shall be visible to each other.
The semantics of assignments to variables passed by reference is
that changes are seen outside the subroutine immediately (before the subroutine returns).
[Ben] Based on this, I can see why ip2==5 is correct since the "a" being passed
is a reference to the variable "a" which is now 5.
The correct result is ip1 == 4 // the sampled value
ip2 == 5 // the variable "a" value at call time
a == 5 // the value in the Observed region
Another opinion on this: This is a gray area in the LRM. The arguments passed to the task should be sampled, but if it is passed by reference, it is not clear what applies. Clearly one vendor decided to sample it too, not the reference but the variable referred to.
As far as ‘a’ is concerned, in principle it should be sampled.
So ip1 should be 4 ip2 is debatable, 4 or 5…
It anyway does not make sense to pass by ref in the case of assertions.