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

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.

Below code shows how to use try_get and try_peek methods.

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.

Sini Balakrishnan

Sini Balakrishnan

Staff Engineer at Intel
Sini has spent more than a dozen years in the semiconductor industry, focusing mostly on verification. She is an expert on Formal Verification and has written international papers and articles on related topics.
Sini Balakrishnan

Latest posts by Sini Balakrishnan (see all)

4 Comments

  1. praveen

    is it legal to write put() and peek()/get() method in same task to see what has been put into the mailbox…

    eg.

    task send_to_mbx(int i);
    int j;
    $display(” Sending Packet to Mailbox – put() : %0d”, i);
    mbx.put(i);
    mbx.get(j); //or mbx.peek(j);
    $display(” Sent Packet to Mailbox – get() : %0d”, j);
    endtask

    if its not then could you please explain why?

    ps: very helpful and very well explained.. thanks alot..

Leave a Reply

Your email address will not be published. Required fields are marked *