The order in which the spawned threads are scheduled is not defined. This particular simulator chose to switch to the last spawned thread first (the thread that prints 2). It’s actually pretty cool that it did that, because this way we can also see that we shouldn’t rely on any specific execution order when it comes to parallel threads, unless we use explicit synchronization mechanisms (such as semaphores).
Also, thanks for the tip with the extra #0 delay. This works inside tasks, where you’re allowed to consume time, but if you have a function that spawns multiple threads, then you won’t be allowed to do any delays (# statements, @ statements, etc.).
You are right about the order. It’s just that I’ve never seen reversed order with the simulators I used.
As to the #0, it’s particularly useful when fork/join_none is used and you want to get the spawned thread run without advancing time. In fact, it’s used in UVM source codes.
Good posts~
Using #0 is the wrong thing to do. It is a hack that is a short term fix that creates problems later. The #0’s in the UVM and other code create unnatural ordering issue that are fixed by adding extraneous loops of #0s. The problem using them to fix the example here is that instead of getting parallel threads, you get a series of ordered threads delayed by one delta cycle. -dave_59