Fork-join dilema

I need to know which thread of a fork-join caused the fork to exit, after the fork has been disabled, example

fork
  begin
    @blocking_cond1;
  end
  begin
    @blocking_cond2;
  end
join_any
disable fork;

When the fork drops out at the end, how can I tell which condition caused the fork to disable ?

Could do this

a = 0;
fork
  begin
    @blocking_cond1;
    a = 1;
  end
  begin
    @blocking_cond2;
    a = 2;
  end
join_any
disable fork;

case (a)
  0: call0();
  0: call1();
endcase

But this is assigning the same variable in two branches of a fork, which is incorrect

Does anyone know of a better way of doing this, or can point me in the right direction?

Take a look at fine-grain process control in System Verilog. Use the ‘process’ keyword to declare a special built-in class and you can reference each process’ status to see which one finished first.

Do you need to know this in order to debug a problem with your code, or does the code need to know this for some other functionality?

A debugging tool like Questa with a hierarchical thread viewer will show you which thread is still active if you set a breakpoint on the disable fork statement.

You can write values into a queue to know which thread finished first.

int q[$];
fork
  begin
    @blocking_cond1;
    q.push_back(1);
  end
  begin
    @blocking_cond2;
    q.push_back(2);
  end
join_any
disable fork;
 
case (q.pop_front())
  1: call0();
  2: call1();
endcase

In reply to edcarstens:

Fine grain process control sounds interesting … I will check this out … thanks

In reply to dave_59:

Hi dave_59

I had a similar solution using two local variables, but the queue method is better. i.e set a, b =0 at the start, then set a=1 in branch one, and b=1 in branch 2, then at the end you can do a compare
{a, b} == 00 (should never occur), 01 and 10, says which branch occurred and 11, again should never occur (simply due to scheduling I assume).

I am not trying to debug an error, this is functional code. Basically when the fork starts, one of two things can occur. If either occur I want to branch off and do something (something that consumes time). So if I branch off when one occurs I need to shutdown the other branch, so that it does not occur (either, or, not both).

So I figured the easiest thing to do was record the occurring event, shut down the fork, then branch off.

Thanks for the ideas

In reply to Tim Ewins:

The case where both processes make assignments to a and b is a legal possibility, but highly unlikely. Verilog does not guarantee atomic execution of statements within a single thread. See https://forum.verificationacademy.com/forum/verification-methodology-discussion-forum/systemverilog-and-other-languages-forum/23057-parallel-execution-threads

In reply to :

I am new to SV. Can you explain why is it incorrect to assign same variable in two branches of fork? In above example, assignment to ‘a’ will happen at different time units.

In reply to jyotsna:

The problem is when both blocking condition events occur in the same time step. If you can guarantee that will never happen, there is no problem with assigning to the same variable from two different threads.

In reply to dave_59:

Thanks for the answer :)