SystemVerilog Interprocess Synchronization and Communication
[Part 1]
Previous: Built-in methods in Semaphore | Next: More methods in Mailbox
Mailbox
Mailboxes are another convenient way for inter-process communication.
Semaphores provide a way for processes to communicate indirectly;
mailboxes are facilities where processes can communicate directly
with one another.
Mailboxes operate in the same manner as a real mailbox. A process may submit
a letter (which, in this case, will contain a data message) for another
process in a mailbox. The message stays in the mailbox until the receiving
process comes and retrieves it. If the receiving process checks the mailbox
before the sending process deposits the message in the mailbox, the receiving
process goes back empty handed.
A message in this case can be any singular type (i.e. any variable other than
an unpacked array, structure or union type). A non-parameterized mailbox
(discussed later) can accept and retain messages of any valid singular type.
The only other restriction is that a message must be a valid left hand side
expression. For example, a net type, such a wire, is not a valid message.
So, you can use a single mailbox to handle various type of messages (from a
single or multiple source). Also, a mailbox can be bounded, meaning it can
hold only a pre-specified maximum number of messages. Or, it can be unbounded,
when it will hold all the messages that it receives.
Syntactically, a mailbox is a built-in class (just as semaphore is, with
all the rules for a general class being equially applicable for mailbox too)
that can be defined as follows.
mailbox uGotMail;
Built-in methods in Mailbox
The class mailbox provides 8 methods that can be used for accessing a
mailbox. These methods are summarized below in the table and then described
in details in the next sections.
Method name
| Summary
|
new()
| Create a mailbox with specified number of slots.
|
num()
| Find the number of messages in a mailbox.
|
get()
| Retrieve a message, if available, from the mailbox. Block
otherwise.
|
try_get()
| Retrieve a message from a mailbox without blocking.
|
peek()
| Copy a message, if available, from the mailbox. Block
otherwise.
|
try_peek()
| Copy a message from a mailbox without blocking.
|
put()
| Put a message in a mailbox.
|
new()
The function new() is the constructor method for the class
mailbox. It takes one integer argument bound that
describes the number
f messages that this mailbox can hold.
If bound is 0, the mailbox can hold (theoretically)
infinite number of messages. The default value of this argument
is 0. The prototype declaration for new() is shown below.
Note that, new() being a function, can not block or
consume time.
function new (int bound = 0);
The following example shows a mailbox declaration that can hold
N_MSG (a non-negative integer) number of messages with a call to
its constructor new.
mailbox uGotMail = new(N_MSG);
num()
As mentioned earlier, num() returns the number of messages
in a mailbox. However, this number changes whenever a process puts
or retrieves a message in a mailbox. So, the validity of the result
of a num() call should be examined carefully before use. In
practice, for this reason, num() is rarely used.
The prototype for num() is shown below. Note that, num(),
similar to new() is a function and hence, non-blocking. It returns
the number of messages in the mailbox and takes no argument.
function int num();
The following example shows a code snippet that prints the number of
messages in a mailbox.
int i;
...
if ((i = uGotMail.num()) == 0)
$display("The mailbox is empty");
else
$display("The mailbox has %d messages", i);
put()
A process uses the put() method to place a message in a mailbox.
This method is a task and if there are not enough places to put the
message in a bounded mailbox, the call will block (i.e. wait until
a place is available). The prototype for put() method is shown
below.
task put (singular message);
The following example illustrates the use of the put method.
Note that, the mailbox uGotMail is used for two different
types of messages, the first one is an integer and second one is
a string.
int msg1;
string msg2;
...
if (msg_is_available) begin
uGotMail.put(msg1);
uGotMail.put(msg2);
end
try_put()
The method try_put() is very similar to put(), except
that it does not block if there is no place available in the mailbox.
The prototype for try_put() method is shown below.
function try_put (singular message);
Previous: Built-in methods in Semaphore | Next: More methods in Mailbox
|