SV_12_Interprocess Communication
摘要:高级且易于使用的同步和通信机制对于控制用于为复杂系统或高度反应性的测试台架建模的动态流程之间发生的交互类型至关重要。
- verilog提供了-> 和 @ ,但仅局限于静态对象,无法处理动态对象;
- SV提供了以下三种方式用于进程键通信:
- semapgore
- mailbox
- events
1 Semaphore
旗语用于锁定(资源无法使用)和解锁(资源可以使用)一个公共资源。
秘钥返回获取类似于fifo。
- semaphore allocation :new()
- using semaphore:get()
- returning semaphore keys:put()
- try to obtain one or more keys without blocking :try-get()
1.1 new()
1 function new(int keyCount = 0 );
- new 创建旗语秘钥;
- keyCount指定旗语的秘钥数量。
1.2 put()
1 task put(int keyCount = 1);
- put():返回一定量的旗语秘钥数量,缺省值为1;
1.3 get()
1 task get(int keyCount = 1);
- get():获得一定数量的秘钥,缺省值为 1;
- 如果现存秘钥数量少于获取 秘钥,则进程阻塞,等待秘钥补充;
1.4 try_get()
1 function int try_get(int keyCount = 1);
- 与get()功能相同,但try_get不会阻塞。
Semaphore例子:
1 program semaphore_ex; 2 3 semaphore semBus = new(1); 4 5 initial begin 6 fork 7 agent("AGENT 0",5); 8 agent("AGENT 1",20); 9 join 10 end 11 12 task automatic agent(string name, integer nwait); 13 integer i = 0; 14 for (i = 0 ; i < 4; i ++ ) begin 15 semBus.get(1); 16 $display("[%0d] Lock semBus for %s", $time,name); 17 #(nwait); 18 $display("[%0d] Release semBus for %s", $time,name); 19 semBus.put(1); 20 #(nwait); 21 end 22 endtask 23 24 endprogram 25 //compile result 26 27 [0] Lock semBus for AGENT 0 28 [5] Release semBus for AGENT 0 29 [5] Lock semBus for AGENT 1 30 [25] Release semBus for AGENT 1 31 [25] Lock semBus for AGENT 0 32 [30] Release semBus for AGENT 0 33 [35] Lock semBus for AGENT 0 34 [40] Release semBus for AGENT 0 35 [45] Lock semBus for AGENT 1 36 [65] Release semBus for AGENT 1 37 [65] Lock semBus for AGENT 0 38 [70] Release semBus for AGENT 0 39 [85] Lock semBus for AGENT 1 40 [105] Release semBus for AGENT 1 41 [125] Lock semBus for AGENT 1 42 [145] Release semBus for AGENT 1
2. Mailbox
进程之间交换消息,进程1向邮箱发送消息,进程2从邮箱里检索消息。
信息的获取和放置严格遵循FIFO原则。
- mailbox allooction : new()
- put()
- try_put()
- get() or geek()
- try_get() or try_geek()
- num():返回邮箱的信息数量
2.1 new()
1 function new(int bound = 0);
- 如果bound = 0,则邮箱是无界的,put()不会阻塞;
2.2 num()
1 function int num();
- num()的返回值只在邮箱执行下一个get()和或put()之前有效。
2.3 put()
1 task put( singular message)
- 如果邮箱是有界的,邮箱满了之后,put()将挂起,直到邮箱有多余的空间放置消息。
2.4 try_put()
1 function int try_put( singular message);
功能与put()相同,如果邮箱是满的,则会返回0,不会挂起 。
2.5 get()
1 task get( ref singular message );
- 消息类型需要与邮箱中的消息类型一致;
- 如果邮箱是空的,则进程将会挂起,直到有新的消息放入。
2.6 try_get()
1 task get( ref singular message );
- 功能与get()类似,如果邮箱是空的,则会返回0,不会阻塞;
2.7 peek()
1 task peek( ref singular message );
- 不同于get()的是,geek()操作是复制信息,邮箱中的信息会保留。
- 如果邮箱是空的 ,则进程会挂起,直到有新的消息被放置在邮箱中。
2.8 try_peek()
1 function int try_peek( ref singular message );
- 功能与peek()类似,如果邮箱是空的,则会返回0,不会阻塞;
mailbox例子:
1 program mailbox_ex; 2 mailbox checker_data = new(); 3 4 initial begin 5 fork 6 input_monitor(); 7 checker(); 8 join_any 9 #1000; 10 end 11 12 task input_monitor(); 13 begin 14 integer i = 0; 15 // This can be any valid data type 16 bit [7:0] data = 0; 17 for(i = 0; i < 4; i ++) begin 18 #(3); 19 data = $random(); 20 $display("[%0d] Putting data : %x into mailbox", $time,data); 21 checker_data.put(data); 22 end 23 end 24 endtask 25 26 task checker(); 27 begin 28 integer i = 0; 29 // This can be any valid data type 30 bit [7:0] data = 0; 31 while (1) begin 32 #(1); 33 if (checker_data.num() > 0) begin 34 checker_data.get(data); 35 $display("[%0d] Got data : %x from mailbox", $time,data); 36 end else begin 37 #(7); 38 end 39 end 40 end 41 endtask 42 43 endprogram 44 45 //compile result 46 47 [3] Putting data : 24 into mailbox 48 [6] Putting data : 81 into mailbox 49 [9] Putting data : 09 into mailbox 50 [9] Got data : 24 from mailbox 51 [10] Got data : 81 from mailbox 52 [11] Got data : 09 from mailbox 53 [12] Putting data : 63 into mailbox 54 [12] Got data : 63 from mailbox
3. Event
- 命名为events的触发状态会在事件触发的整个时间步长中持续存在;
- event还可以充当同步队列的句柄,因此,events是可以作为参数传递给任务,可以相互分配或进行比较。
3.1 触发一个阻塞事件
- ->(电平敏感)
- 将解除等待该事件的所有阻塞进程;
3.2 触发一个非阻塞事件
- ->>(电平敏感)
- 在延迟控制过期或事件控制发生的时间内创建一个非阻塞的assign update 事件。
3.3 等待一个事件
- @(边沿敏感)
- 只能先等待再触发,不可以先触发再等待。
3.4 wait_order()
- 将挂起调用进程,直到所有指定的事件都按照给定的顺序(从左到右)触发。
- 如果指定事件的顺序被打乱触发,将会导致操作失败。
event例子
1 program event_t; 2 event try_event; 3 event get_event; 4 5 initial begin 6 // Start the wait_event as parallel thread 7 fork 8 wait_event(); 9 join_none 10 11 // Wait till task wait_event has started execution 12 $write("Waiting for event get_event\n"); 13 @ (get_event); 14 $write("Triggering event try_event\n"); 15 #1; 16 -> try_event; 17 // Wait till task wait_event has done execution 18 $write("Waiting for event get_event\n"); 19 wait (get_event.triggered); 20 $write("Got event get_event\n"); 21 #10 $finish; 22 end 23 24 // Task which triggers/waits for events 25 task wait_event(); 26 begin 27 #1; 28 // Inform that wait_event has started 29 $write("--task : Triggering event get_event\n"); 30 -> get_event; 31 $write("--task : Waiting for event try_event\n"); 32 @(try_event); 33 $write("--task : Got event try_event\n"); 34 // Inform that wait_event has done with execution 35 #1; 36 $write("--task : Triggering event get_event\n"); 37 ->get_event; 38 end 39 endtask 40 41 endprogram 42 43 //compile result 44 45 Waiting for event get_event 46 --task : Triggering event get_event 47 --task : Waiting for event try_event 48 Triggering event try_event 49 Waiting for event get_event 50 --task : Got event try_event 51 --task : Triggering event get_event 52 Got event get_event
浙公网安备 33010602011771号