System Verilog中的Mailboxes

描述

Mailboxes是进程间通信的另一种方式,但是比semaphores更强大,因为Mailboxes可以在两个进程之间交换消息。

数据可以由一个进程发送,由另一个进程获取,顾名思义就像是邮箱一样。

获取邮箱中信件的方式有两种:
1、一直等待信件的到来(blocking
2、如果没有信件就先去干其他事情,过一会儿再来看是否信件到了。(non-blocking

从Mailboxes中可以存放信件规模的角度,Mailboxes可以大致分为bounded Mailboxesunbounded Mailboxes

bounded Mailboxes就是指Mailboxes中能够容纳有限数量的信件,如果在Mailboxes满时写入会阻塞住,直到不满。unbounded Mailboxes可以容纳无限数量的信件。

Mailboxes也可以声明为只能存放某一类的信件。默认情况下,Mailboxes是无类型的,这意味着Mailboxes可以发送和接收任何不同类型的信件。

邮箱声明的语法是:

 

mailbox mbox;

 

Mailbox是一个SystemVerilog内置类,自然也提供了许多内置的方法:

1、new ()
创建一个mailbox,函数原型是:

 

function new ( ) (int bound = 0);

 

会返回一个mailbox句柄,默认bound是0,表示unbounded mailbox。

2、num ()
返回mailbox中信件的个数,函数原型是:

 

function int num( );

 

3、put ()
blocking put(按照FIFO顺序),如果mailbox满了会阻塞进程,函数原型是:

 

task put (singular message)

 

4、try_put ( )
non-blocking put(按照FIFO顺序),如果mailbox满了不会阻塞进程,会返回值0。函数原型是:

 

function try_put (singular message);

 

5、get ()
blocking get(按照FIFO顺序),如果mailbox是空的,会一直blocking进程。函数原型是:

 

task get ( ref singular message);

 

6、try_get ( )
non-blocking get(按照FIFO顺序),如果mailbox是空的,不会阻塞进程,会返回值0。函数原型是:

 

function int try_get( ) (ref singular expression)

 

7、peek ( )
peek()不同于get(),peek会复制mailbox中的信件,而不会将信件从mailbox中删除。函数原型是:

 

task peek (ref singular message);

 

如果mailbox是空的,会一直block进程。
8、try_peek (),不过多言说,non-block peek。函数原型是:

 

function int try_peek ( ref singular expression)

 

示例:

 

module mB;
 bit [7:0] mem [0:3];
 int i, j, data;
 mailbox mbox; //declare a mailbox
 
 initial begin
 mbox = new (4); //create a bounded mailbox
 
 fork
 DMA_write;
 CPU_read; 
 join 
 end
 
 task DMA_write; 
 $display($stime,,, "DMA puts Mem Data into mbox");
 for (i=0; i < 4; i++) begin
 mem[i] = $urandom;
 $display($stime,,, "DMA WRITE[%0d] = %0d",i,mem[i]);
 mbox.put(mem[i]); //put data into the mailbox
 end
 endtask
 
 task CPU_read;
 $display($stime,,, "CPU retrieves Mem Data from mbox");
 for (j=0; j < 4; j++) begin
 mbox.get(data); //retrieve data from the mailbox
 $display($stime,,, "CPU READ[%0d] = %0d",i,data);
 end 
 endtask
 
endmodule

 

仿真log:

 

 0 DMA puts Mem Data into mbox
 0 DMA WRITE[0] = 36
 0 DMA WRITE[1] = 129
 0 DMA WRITE[2] = 9
 0 DMA WRITE[3] = 99
 0 CPU retrieves Mem Data from mbox
 0 CPU READ[0] = 36
 0 CPU READ[1] = 129
 0 CPU READ[2] = 9
 0 CPU READ[3] = 99
 V C S S i m u l a t i o n R e p o r t

 

上面这个例子首先声明了一个mailbox “mbox”,然后例化深度为4。

后面两个并行的进程“DMA_write”和“CPU_read” 。从打印log来看并不存在两个进程之间的冲突。

参数化Mailbox

如果希望在mailbox put和get时进行类型检查,可以显式地声明mailbox的类型。

 

module pMailbox; 
 typedef mailbox #(string) string_mbox;
 string s;
 
 initial begin
 static string_mbox SMbox = new;
 s = "hi";
 SMbox.put( s );
 $display("String 'put' is %s", s);
 SMbox.get( s ); 
 $display("String 'get' is %s", s);
 end
endmodule

 

仿真log:

 

String 'put' is hi
String 'get' is hi

 

  审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分