Lately we have been asked by several customers about the concurrency options in Specman (some refer to it as “What are the Specman options similar to fork…join?”). Apparently, things that are in Specman for ages are likely to be missed. Therefore, this blog describes Specman concurrent actions (existing for years).
Specman has two actions controlling concurrent execution: all of and first of. Both actions create parallel branches which might start or call TCMs:
- all of awaits completion of all branches (similar to the Verilog fork…join).
- first of terminates at the first completion of any branch (similar to the SystemVerilog fork…join_any).
For demonstrating the various concurrency options, let’s take an example of a simple task of feeding a child. We usually give children both food and milk for dinner. This can be represented as:
unit child {
eat() @sys.any is {
wait [90] * cycle;
message(LOW, "Child ate all the food");
};
drink() @sys.any is {
wait [40] * cycle;
message(LOW, "Child drank all the milk");
};
};
Now, let’s do both the tasks of giving food and milk in parallel.
Example 1: Using first of
The first example is of a tired father. He will be happy if the child either finishes the food or the milk. He doesn’t expect the child to finish both the food and the milk. In this case, he will use first of.
extend child {
have_dinne r() @sys.any is {
first of {
{ eat ()};
{ drink ()};
};
message(LOW,"Child either finished eating or drinking, anyway dinner is finished");
};
};
And, here is the result of running this code. As you can see – this dinner is finished after the child finishes the milk. The eat() TCM never ends.
Running the test ...
[40] child-@1: Child drank all the milk
[40] child-@1: Child either finished eating or drinking, anyway the meal is finished
Last specman tick - stop_run() was called
Example 2: Using all of
On the weekend, father has more patience. So, he decides to wait until the child finishes both the food and the milk. So now he uses all of. The all off action will finish only after both eat() and drink() are completed.
extend child {
have_weekend_dinner () @sys.any is {
all of {
{ eat ()};
{ drink()};
};
message(LOW,
"Child finished both eating and drinking, dinner is finished ");
};
};
And, here is the result of running this code. As you can see – the meal finishes only after both TCMs ended.
Running the test ...
[40] child-@1: Child drank all the milk
[90] child-@1: Child ate all the food
[90] child-@1: Child finished both eating and drinking, dinner is finished
Last specman tick - stop_run() was called
Example 3: Using all of while starting a TCM
The third example is of a father who is in a real hurry and needs to work while giving the child dinner. He gives the child dinner but does not wait to see if the child finishes it. In terms of coding, this busy father start the TCM, rather than calling it.
extend child {
have_dinner_father_working() @sys.any is {
all of {
{start eat()};
{start drink()};
};//all
message(LOW, "Child started eating and drinking, father needs to work ");
};
};
And, the outcome of running this TCM:
[0] child-@1: Child started eating and drinking, father needs to work
[40] child-@1: Child drank all the milk
[90] child-@1: Child ate all the food
Last specman tick - stop_run() was called
We hope these examples will help you better understand concurrent options and you will enjoy using these options!
Also, note that we are working on some enhancements around these areas. So, stay tuned!!!
Orit Kirshenberg
Specman team