System Verilog : Mailbox

Synchronization and communication mechanisms are essential in our design, to control the interactions between processes or with a reactive testbench. This can be easily handled in System Verilog using semaphores, mailboxes and named events.

Mailboxes are a message-based process synchronization and communication mechanism provided in SV. It allows messages to be exchanged between processes. Conceptually, mailboxes behave like real mailboxes with delivery and retrieval of messages. In this, data can be sent to mailbox by one process and retrieved by another.

Example of creating a mailboxes are

1

2

mailbox mbx1=new;

mailbox mbx2=new(5);

Bounded and Unbounded Mailboxes
If maximum capapcity of the mailbox is specified along with the constructor, it is called bounded mailbox. If you do not pass a value to constructor, it would be an unbounded mailbox. A bounded mailbox becomes full when it reaches the maximum number of messages. But unbounded mailbox can never be full, as it has unlimited capacity.

Mailboxes can be created using bounded or unbounded queue size as per your requirement. In the above case, mbx1 is an unbounded mailbox and mbx2 is a bounded mailbox.

Following built-in methods are available to do communication using mailboxes.

new() : Create a mailbox

put() : Place a message in a mailbox

try_put() : Try to place a message in a mailbox without blocking

get() : Retrieve a message from a mailbox

try_get() : Try to retrieve a message from a mailbox without blocking

peek() : Copy a message from a mailbox without removing

try_peek() : Try to copy a message from a mailbox without blocking & removing

num() : Retrieve the number of messages in the mailbox

Following code shows how to use new(), num(), get() and put() built-in methods for mailbox.

The new() method returns the mailbox handle. If the bound argument is 0, then the mailbox is unbounded. Here mbx is an unbounded mailbox. If bound is nonzero, it represents the size of the mailbox queue.

The number of messages in a mailbox can be obtained via the num() method. It returns the number of messages currently in the mailbox. In the above case, 5 messsages are there in the mailbox mbx at time 50. So the method returns 5.

The put() method places a message in a mailbox. This is a blocking method and stores the message in the mailbox in strict FIFO order. If the mailbox was created with a bounded queue, the process shall be suspended until there is enough room in the queue. In the above code, from time 10 to 50, 5 messages are placed in the mbx using put() method.

The get() method retrieves a message from a mailbox and also removes it from the mailbox queue. If the mailbox is empty, then the current process is blocked until a message is placed in the mailbox. If the type of the message variable and the type of the message in the mailbox are different, a run-time error is generated.

The peek() method copies a message from a mailbox without removing the message from the queue.If the mailbox is empty, then the current process blocks until a message is placed in the mailbox. If type of the message variable and the type of the message in the mailbox are different, a run-time error is generated.

From time 70 to 150 all 5 messages are retrieved and removed from queue. Again two more messages are sent to mailbox. At time 180, get() method retrieves “700” and the message left in the mailbox is “900”. The method peek() just copies that and when we do get() again, 900 will be retrived and mbox will be emptied.

Here we can see that peek() will not retrieve & remove the messages from the queue; instead it just copies. But get() method removes the message from the mailbox after retrieval.

The try_get() method attempts to retrieve a message from a mailbox without blocking.If the mailbox is empty, then the method returns 0. This can be found in the above code.

If the type of the message variable and the type of the message in the mailbox are different, the method returns a negative integer. Here string is passed with try_get (inplace of int) and it returns -1.

The try_peek() method attempts to copy a message from a mailbox without blocking & without removing from mailbox queue.If the mailbox is empty, then the method returns 0. If there is a type mismatch the method returns a negative integer.

Here mbx is an bounded mailbox with size 5. The try_put() method attempts to place a message in a mailbox. It stores a message in the mailbox in strict FIFO order. This method is meaningful only for bounded mailboxes. If the mailbox is not full, then the specified message is placed in the mailbox, and the function returns a positive integer. If the mailbox is full, the method returns 0. In the above code, try_put on messages “400”, “500” & “600” fail as mbx is full.