学习目标:
通过下文了解Event、Semaphore、mailbox三种对象的概念、使用方法及应用场景
参考资料:
https://www.chipverify.com/systemjava/systemjava-interprocess-communication
https://www.cnblogs.com/xh13dream/p/9051089.html
https://blog.csdn.net/weixin_43249032/article/details/84035517
Event是同步两个或多个不同进程的一种方式。一个 Event是一个静态对象句柄,用于多个并发活动进程间进行同步。一个或多个进程等待事件发生,另一个进程触发事件,当事件被触发时,等待事件发生的进程将会恢复执行
创建事件 :
event event_name; //creat an event called "event_name"event event_alias = event_name; //两个事件同时指向一个同步对象event event_name = null; //当前时间没有同步对象触发事件:
//use "->" or "->>"operator->event_name;//any process that has access to "event_name" can trigger the event等待事件发生:
//use "@" operator or wait(); @ 和wait() 操作符同一时刻会出现竞争现象 @是边沿敏感 ,wait(event_name.triggered)是电平触发//事件的触发状态只会在当前时间步长保持,一但仿真开始向前运行,就会失去这个状态。@event_name;//orwait(event_name.triggered);//or wait_order(event_name1,event_name2,event_name3) //必须按照当前依次的顺序进行触发,才能触发下面语句,可以使用 wait_order()...else...语句 2、用法实例 // Create an event variable that processes can use to trigger and wait event event_a; // Thread1: Triggers the event using "->" operator at 20ns initial begin #20 ->event_a; $display ("[%0t] Thread1: triggered event_a", $time); end // Thread2: Starts waiting for the event using "@" operator at 20ns initial begin $display ("[%0t] Thread2: waiting for trigger ", $time); #20 @(event_a); $display ("[%0t] Thread2: received event_a trigger ", $time); end // Thread3: Starts waiting for the event using ".triggered" at 20ns initial begin $display ("[%0t] Thread3: waiting for trigger ", $time); #20 wait(event_a.triggered); $display ("[%0t] Thread3: received event_a trigger", $time); end仿真结果见下
待完善
Systemverilog- Semaphore 1、基本概念semaphore是一个内建的类,它提供下列方法:
NameDescriptionfunction new (int keyCount = 0);Specifies number of keys initially allocated to the semaphore bucketfunction void put (int keyCount = 1);Specifies the number of keys being returned to the semaphoretask get (int keyCount = 1);Specifies the number of keys to obtain from the semaphorefunction int try_get (int keyCount = 1);Specifies the required number of keys to obtain from the semaphore创建num个key的semaphore function
semaphore_name = new(number_of_keys) semaphore使用new()方法创建,Keycount指定初始化分配到semaphore的key数量,,缺省值为0,在使用中,放入的数量比取出来的多的时候,桶中所拥有的key数量可以超过默认的Keycount。缺省值为0,new()函数产生semaphore的句柄,如果产生失败,则返回null。
从桶中取出n个key:get() task
semaphore_name.get(number_of_keys); or semaphore_name.get() get()方法可以从桶中获取指定数量的key,缺省值为1,如果指定数目的key存在,则方法返回进程继续执行;如果不存在指定数目的key,进程会阻塞直到对应数量的key出现
向桶中放回多个key:put() function
put()方法会向桶中放置指定数量的key,缺省值为1,无返回值
semaphore_name.put(number_of_keys); or semaphore_name.put()尝试无阻塞的取出多个key:try_get() function
try_get()方法可以用来无阻塞的获取指定数目的key,缺省值为1,有返回值,如果key存在,则返回1并继续执行;如果指定数量的key不存在,则try_get方法返回0
semaphore_name.try_get(number_of_keys); or semaphore_name.try_get() 2、用法实例 从下面例子可以看出,只有一个key时,第二个display()会阻塞到第一个display执行完成后,而当存在两个key时,两个进程可以同时进行;
module semaphore_exp(); semaphore sema; semaphore sema2; initial begin sema = new(1); fork begin display(); end begin display(); end join #10; sema.put(1); fork begin display(); end begin display(); end join end task display(); sema.get(1); $display("runtime = %d",$time); #30; sema.put(1); endtask : displayendmodule 3、UVM中使用方式解析: 待完善
Systemverilog-mailbox mailbox 是一中允许不同进程相互交换数据的方法,mailbox是一个内置类,本质上类似于队列,但和queue队列的数据类型有很大不同,使用semaphore来控制存储队列中的push和pull。无法访问邮箱队列中的给定索引,只能按照fifo的顺序检索项目。
1、基本概念 **mailbox 可以被创建为两种:** 有界队列。
mailbox mailbox_name = new(mailbox_space_number); 只能存储有限个数据量。当一个进程试图将多个消息存入一个满的mailbox中时,将会被挂起直到mailbox中有足够的空间。
无界队列。
mailbox mailbox_name = new(); 可以存储无限个数据量
mailbox有两种类型:
通用邮箱:
mailbox #() mailbox_name; or mailbox mailbox_name; 调用时不带类型参数的即为通用邮箱。通用及为无类型,即单个mailbox可以发送和接收任何类型的数据,但是也存在存储数和获取数据变量间的类型不匹配而导致运行错误的问题。
参数化邮箱:
mailbox #(type = dynamic_type) mailbox_name; 只能传输特定类型的数据,dynamic_type可以执行运行时的类型检查
mailbox的方法和功能函数:
FunctionDescriptionfunction new (int bound = 0);Returns a mailbox handle, bound > 0 represents size of mailbox queuefunction int num ();Returns the number of messages currently in the mailboxtask put (singular message);Blocking method that stores a message in the mailbox in FIFO order; message is any singular expressionfunction int try_put (singular message);Non-blocking method that stores a message if the mailbox is not full, returns a postive integer if successful else 0task get (ref singular message);Blocking method until it can retrieve one message from the mailbox, if empty blocks the processfunction int try_get (ref singular message);Non-blocking method which tries to get one message from the mailbox, returns 0 if emptytask peek (ref singular message);Copies one message from the mailbox without removing the message from the mailbox queue.function int try_peek (ref singular message);Tries to copy one message from the mailbox without removing the message from queue2、用法实例 module sim_top();mailbox m_mbx = new(2); initial begin for (int i = 0; i < 5; i ++) begin m_mbx.put(i); $display("[%0t] Thread0: put item #%d,size=%d",$time,i,m_mbx.num()); #1; end end initial begin forever begin int index; m_mbx.get(index); $display("[%0t] Thread1: get item #%d,size=%d",$time,index,m_mbx.num()); #2; end endendmodule输出:
在time为0 ,100,200,300,400时刻put数据,在0,200,400,600,800时刻将数据取出
2、参数化邮箱
module sim_top();typedef mailbox #(string) s_mbx;class transmitter; s_mbx bound; string s; task send(); for (int i = 0; i < 5; i ++) begin $sformat(s, "name_%0d", i); bound.put(s); $display("[%0t] bound:%0s size=%0d",$time,s,bound.num()); #1; end endtaskendclass : transmitterclass receiver; s_mbx list; string s; task rec(); forever begin list.get(s); $display("[%0t] list:%0s size=%0d",$time,s,list.num()); #2; end endtaskendclass : receivers_mbx mbx = new();receiver name_rec = new();transmitter name_trans = new();initial begin name_trans.bound = mbx; name_rec.list = mbx; fork begin name_trans.send(); end begin name_rec.rec(); end join end仿真结果:
数据i从int转换为string类型传递至receiver,
在time为0 ,100,200,300,400时刻put数据,在0,200,400,600,800时刻将数据取出
3、UVM中mailbox的使用方法分析: 待完善。。。