mailbox

A combination of class and queue is mailbox, A mailbox is a communication mechanism that allows messages to be exchanged between processes. Data can be sent to a mailbox by one process and retrieved by another.

SystemVerilog mailboxes behave like real mailboxes. When a letter is delivered to a mailbox, the letter can be retrieved If the post has not yet been delivered, a process can:

  • Choose to wait for post delivery, or
  • Come back later and check again
  • There are two types of mailboxes


    1. Generic Mailbox (type-less mailbox)There are two types of mailboxes
    The default mailbox is type-less, that is, a single mailbox can send and receive any type of data.
    mailbox mailbox_name;

    2. Parameterized mailbox (mailbox with particular type)
    mailbox is used to transfer a particular type of data.
    mailbox#(type) mailbox_name;

    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.

    mailbox syntax

    mailbox name_of_mailbox;

    mailbox procducer2consumer = new(); // generic mailbox declaration
    mailbox gen2drv= new();// generic mailbox declaration

    mailbox #(packet)procducer2consumer = new();//Parameterized mailbox
    mailbox #(packet)gen2drv= new();//Parameterized mailbox

    mailbox procducer2consumer= new(5); // generic mailbox declaration with constructor
    mailbox gen2drv= new(5);// generic mailbox declaration with constructor

    mailbox #(packet)procducer2consumer= new(5);//Parameterized mailbox with constractor
    mailbox #(packet)gen2drv= new(5);//Parameterized mailbox with constractor

    Built-in methods in Mailbox


    The class mailbox provides 8 methods that can be used for accessing a mailbox.
    new( ) : Create a mailbox with specified number of slots.
    num( ) : Find the number of messages in the mailbox
    get( ) : Retrieve a message, if available, from the mailbox. Block otherwise.
    try_get( ) : Retrieve a message from the mailbox without blocking.
    peek( ) : Copy a message, if available, from the mailbox. Block otherwise.
    try_peek( ) : Copy a message from the mailbox without blocking.
    put( ) : Put a message in the mailbox.
    try_put( ) : Put a message in the mailbox without blocking.

    new()

    function new(int bound = 0);

  • The new() function returns the mailbox handle or, if the mailbox cannot be created, null.
  • If the bound argument is 0, then the mailbox is unbounded (the default) and a put() operation shall never block.
  • num( )

    The number of messages in a mailbox can be obtained via the num() method.
    function int num();

  • The num() method returns the number of messages currently in the mailbox.
  • The returned value should be used with care because it is valid only until the next get() or put() is executed on the mailbox.
  • put()

    The put() method places a message in a mailbox.
    task put( singular message);
    The message is any singular expression, including object handles.
    If the mailbox was created with a bounded queue, the process shall be suspended until there is enough room in the queue.

    try_put()

    This 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 : function int try_put( singular message);

    get()

    The get() method retrieves a message from a mailbox.

    task get( ref singular message );

  • If the mailbox is empty, then the current process blocks until a message is placed in the mailbox.
  • If the type of the message variable is not equivalent to the type of the message in the mailbox, a run-time error is generated.
  • try_get()

    The try_get() method attempts to retrieves a message from a mailbox without blocking.

    function int try_get( ref singular message );

  • The try_get() method tries to retrieve one message from the mailbox.
  • If the mailbox is empty, then the method returns 0.
  • peek()

    The peek() method copies a message from a mailbox without removing the message from the queue.
    The prototype for peek() is:

    task peek( ref singular message );
    The message can be any singular expression, and it must be a valid left-hand side expression.
    The peek() method copies one message from the mailbox without removing the message from the mailbox queue.
    If the mailbox is empty then the current process blocks until a message is placed in the mailbox.
    If there is a type mismatch between the message variable and the message in the mailbox, a runtime error is generated.

    try_peek()

    method attempts to copy a message from a mailbox without blocking.
    function int try_peek( ref singular message );

    Examples

    //-------------------------------------------------------------------------
    // Packet
    //-------------------------------------------------------------------------
    class packet;
      rand bit [7:0] src_addr;
     rand bit [7:0] src_data;
    // display the generated values //
    task print();
    $display("Packet::src_addr=%0d,src_data=%0d",src_addr,src_data);
    endtask
    endclass
    //-------------------------------------------------------------------------
    //Generator - Generates the transaction packet and send to driver
    //-------------------------------------------------------------------------
    class generator;
    packet pkt;
    mailbox gen2drv;
    //constructor, getting mailbox handle
    function new(mailbox gen2drv);
    this.gen2drv = gen2drv;
    endfunction
    task run;
    repeat(10) begin
    pkt = new();
    pkt.randomize(); //generating packet
    gen2drv.put(pkt); //putting packet into mailbox
    $display("Generator:: Generate the data and Put into Mailbox");
    pkt.print();
    #10;
    end
    endtask
    endclass
    //-------------------------------------------------------------------------
    // Driver - Gets the packet from generator and display's the packet items
    //-------------------------------------------------------------------------
    class driver;
      packet pkt;
     mailbox gen2drv;
      //constructor, getting mailbox handle
      function new(mailbox gen2drv);
    this.gen2drv = gen2drv;
    endfunction
    task run;
    repeat(10) begin
    gen2drv.get(pkt); //getting packet from mailbox
    $display("Driver Packet Recived");
    pkt.print();
    end
    endtask
    endclass
    //-------------------------------------------------------------------------
    // tbench_top
    //-------------------------------------------------------------------------
    module mailbox_ex;
    generator gen;
    driver dri;
    mailbox gen2drv; //declaring mailbox gen2drv
    initial begin
    //Creating the mailbox, Passing the same handle to generator and driver,
    //because same mailbox should be shared in-order to communicate.
    gen2drv= new(); //creating mailbox
    gen = new(gen2drv); //creating generator and passing mailbox handle
    dri = new(gen2drv); //creating driver and passing mailbox handle
    $display("------------------------------------------");
    fork
    gen.run(); //Process-1
    dri.run(); //Process-2
    join $display("------------------------------------------");
    end
    endmodule