Communicating multiple producers to single consumer using mailbox

Hello,

I’ve seen several examples of using mailboxes, to communicate between single producer and consumer “components”, basically I can have a mailbox on each of them and then when connecting them together I just assign the mailbox handles something like this:


module env();
  producer prod;
  consumer cons;
  packet pkt;
  mailbox #(packet)channel; 
 
  initial begin
    channel= new(); //creating mailbox
    prod= new(channel); //passing mailbox handle
    cons= new(channel); //passing mailbox handle
    fork
      prod.run(); 
      cons.run(); 
    join
  end
endmodule

I want to connect multiple producers to a single consumer (something similar when in UVM you have a component connected to several analysis exports from other components) Is there a better way of doing this than the following (Are there any risks on this approach?):


module env();
  producer prod[];
  consumer cons;
  packet pkt;
  mailbox #(packet)channel; 
 
  initial begin
    
    channel= new(); //creating mailbox
    prod= new[4]; // create dynamic array of producers
    foreach(prod[i]) begin
       prod[i] = new(channel); //passing mailbox handle to each producer
    end
    cons= new(channel); //passing mailbox handle
    fork
      foreach(prod[i]) begin
        prod.run(); 
      end
      cons.run(); 
    join
  end
endmodule

PS: I know I could use UVM and avoid these questions but due to project’s restrictions I’m forced to use only SV.

Cheers,

-Ronald

In reply to rgarcia07:

Do you mean to run the 4 producers in series (which is what you have written), or do you want them executing in parallel? If in parallel, you may need some sort of arbitration scheme to keep one of the producers from being greedy.

In reply to dave_59:

In reply to rgarcia07:
Do you mean to run the 4 producers in series (which is what you have written), or do you want them executing in parallel? If in parallel, you may need some sort of arbitration scheme to keep one of the producers from being greedy.

Hi Dave,

I meant to act in parallel, any hint on how to achieve this is really appreciated, I thought that putting the prod[i].run() methods inside the fork-join I will get the each producer’s put() task running in parallel and blocking the mailbox.

module env();
  producer prod[];
  consumer cons;
  packet pkt;
  mailbox #(packet)channel; 
 
  initial begin
 
    channel= new(); //creating mailbox
    prod= new[4]; // create dynamic array of producers
    foreach(prod[i]) begin
       prod[i] = new(channel); //passing mailbox handle to each producer
    end
    cons= new(channel); //passing mailbox handle
    fork
      foreach(prod[i]) begin
        fork
          prod.run(); 
        join
      end
      cons.run(); 
    join
  end
endmodule

Cheers,
-Ronald

In reply to rgarcia07:
In your original example, the foreach statement executes as a single process. In your second example, a fork-join with a single statement behaves the same as begin/end.

You need to use fork-join_none to spawn independent processes.

initial begin
    channel= new(); //creating mailbox
    prod= new[4]; // create dynamic array of producers
    foreach(prod[i])
       prod[i] = new(channel); //passing mailbox handle to each producer
    cons= new(channel); //passing mailbox handle
    foreach(prod[i])
        fork
          automatic int k=i;
          prod[k].run(); 
        join_none
    cons.run(); 
  end

In reply to dave_59:

Duh, I totally forgot the join_none, as usual many thanks for your help Dave :-)