SV线程内部通信

写在前面:欢迎您,有缘人!

1.内部线程通信

线程之间需要通信,实现对执行序列的控制

主要有三种:Event based、Resource sharing、Data passing

内部线程通信机制:Verilog event

在Verilog中,@操作符是边沿敏感的,它总是阻塞着,等待着事件的变化。其他的线程可以通过->操作符来触发事件。

 Verilog event

  •  Verilog语言中使用 event同步线程
  • 触发事件的操作符:->

不会阻塞线程的执行

  • 等待事件被触发@

◆边沿敏感,总会阻塞线程执行

◆只有当事件发生变化时,线程才会继续执行

  • 当阻塞线程之前发生触发线程时,可能引起竞争现象

内部线程通信机制:SV event

SystemVerilog引入了triggered()函数,可用于查询某个事件是否已经被触发,包括在当前时刻。线程可以等待这个函数的结果,而不用在@操作符上阻塞。

Systemverilog event

  • 同步线程
  • event是一个同步对象的句柄,可以当做参数传递给子程序

不需要声明为全局变量,就可以将 event作为共享资源使用

  • 触发一个事件的操作符:->和->>
  • 等待一个事件被触发的操作符:@和wait()
  •  triggered函数用于检查一个事件是否被触发过,返回值是一个状态
  • wait(event.triggered)

如果在当前的仿真时间范围内,事件曾触发过,语句不会被阻塞

否则, wait(event.triggered)语包会一直等待事件被触发

2.内部线程通信机制:旗语


旗语有三种基本操作。可以将旗语看成是一把钥匙,谁拥有钥匙谁就对资源具有使用的权利。旗语可被视为一个互斥体,用于实现对同一资源的访问控制。使用new方法可以创建一个带单个或多个钥匙的旗语,使用get可以获取一个或多个钥匙,而put则可以返回一个或多个钥匙。如果你试图获取一个旗语而不希望被阻塞,可以使用try_get函数。它返回1表示有足够多的钥匙,而返回0则表示要是不够。

实例:用旗语实现对硬件资源的访问控制

//SV绿皮书
//用旗语实现对硬件资源的访问控制
program automatic test(bus_ifc.TB bus)
  semaphore sem;//创建一个旗语
  initial begin
    sem = new(1);//分配一个钥匙
    fork
      sequencer();//产生两个总线事务线程
      sequencer();
    join
  end

task sequencer;
  repeat($urandom%10)//随机等待0-9个周期
    @bus.cb;
  sendTrans();//执行总线任务
endtask;

task sendTrans;
  sem.get(1);//获取总线钥匙
  @bus.cb;//把信号驱动到总线上
  bus.cb,addr <=t.addr;
...

  sem.put(1);//;处理完成时把钥匙返回
endtask
endprogram

如上面实例,旗语重要的几行代码如下:

semaphore sem;创建一个旗语
sem = new(1);分配一把钥匙
sem.get(1);获取一把钥匙
sem.put(1);返回一把钥匙
try_get();获得钥匙而不被阻塞,返回1表示有足够多的钥匙,返回0则表示钥匙不够

 实例:semphore应用实例

//systemverilog与功能验证(钟文枫)
//源代码3-6 semaphore应用实例
//Chapter3 semaphore_example.sv
module semaphore_example();
    semaphore s1=new(1);

    task t1();
        for(int i=0;i<3;i++) begin
            s1.get(1);
            #5;
            $display("t1 owns semaphore");
            s1.put(1);
            #5;
        end
    endtask

    task t2();
        for(int i=0;i<3;i++)begin
            s1.get(1);
            #5;
            $display("t2 owns semaphore");
            s1.put(1);
            #5;
            end
    endtask

    initial begin
        fork
            t1();
            t2();
        join
    end
endmodule

仿真结果:

Compiler version I-2014.03; Runtime version I-2014.03;  Aug 17 13:13 2020
t1 owns semaphore
t2 owns semaphore
t1 owns semaphore
t2 owns semaphore
t1 owns semaphore
t2 owns semaphore
           V C S   S i m u l a t i o n   R e p o r t 

实例:semaphore_ex.sv

//e课网
//semaphore_ex.sv
program semaphore_ex;
  semaphore semBus = new(1);
  
  initial begin
	fork
	  agent("Agent 0",5);
	  agent("AGENT 1",20);
	join
  end
  
  task automatic agent(string name,integer nwait);
    integer i=0;
	for(i=0;i<4;i++)begin
	semBus.get(1);
	$display("[%0d] Lock semBus for %s",$time,name);
	#(nwait);
	$display("[%0d] Release semBus for %s",$time,name);
	semBus.put(1);
	#(nwait);
	end
	endtask
endprogram

 仿真结果:

Compiler version I-2014.03; Runtime version I-2014.03;  Aug 17 13:32 2020
[0] Lock semBus for Agent 0
[5] Release semBus for Agent 0
[5] Lock semBus for AGENT 1
[25] Release semBus for AGENT 1
[25] Lock semBus for Agent 0
[30] Release semBus for Agent 0
[35] Lock semBus for Agent 0
[40] Release semBus for Agent 0
[45] Lock semBus for AGENT 1
[65] Release semBus for AGENT 1
[65] Lock semBus for Agent 0
[70] Release semBus for Agent 0
[85] Lock semBus for AGENT 1
[105] Release semBus for AGENT 1
[125] Lock semBus for AGENT 1
[145] Release semBus for AGENT 1
$finish at simulation time                  165
           V C S   S i m u l a t i o n   R e p o r t 

 实例:semaphore_ex_0.sv

//e课网
//semaphore_ex_0.sv
program semaphore_ex_0;
  semaphore semBus = new(1);
  
  initial begin
	fork
	  agent("Agent 0",5);
	  agent("AGENT 1",20);
	join
  end
  
  task automatic agent(string name,integer nwait);
    integer i=0;
	for(i=0;i<4;i++)begin
	//semBus.get(1);
	$display("[%0d] Lock semBus for %s",$time,name);
	#(nwait);
	$display("[%0d] Release semBus for %s",$time,name);
	//semBus.put(1);
	#(nwait);
	end
	endtask
endprogram

 仿真结果:

Compiler version I-2014.03; Runtime version I-2014.03;  Aug 17 13:37 2020
[0] Lock semBus for Agent 0
[0] Lock semBus for AGENT 1
[5] Release semBus for Agent 0
[10] Lock semBus for Agent 0
[15] Release semBus for Agent 0
[20] Release semBus for AGENT 1
[20] Lock semBus for Agent 0
[25] Release semBus for Agent 0
[30] Lock semBus for Agent 0
[35] Release semBus for Agent 0
[40] Lock semBus for AGENT 1
[60] Release semBus for AGENT 1
[80] Lock semBus for AGENT 1
[100] Release semBus for AGENT 1
[120] Lock semBus for AGENT 1
[140] Release semBus for AGENT 1
$finish at simulation time                  160
           V C S   S i m u l a t i o n   R e p o r t 

注意对照上面两个实例, 明显观看到:

  • Semaphore通常用于对共享资源的分配和同步
  • 在内存中创建 semaphore时,类似于创建一个篮子( bucket),篮子中包含一定数量的钥匙(keys)
  • 进程在执行之前必须获取一个钥匙
  • 当一个特定的进程需要钥匙时,只有一定数量的进程在同时运行

3.内部线程通信机制:信箱

  • Mailbox是SV中不同进程间的通信方式,通过 mailbox可以在不同的进程之间传递信息
  • 将一个进程中的数据,通过 mailbox传递给另外一个进程:当 mailbox中没有数据时,线程将等待
  • Mailbox类似于一个FIFO,可以设置一定的深度queue size

当邮箱中的信息数量达到邮箱的深度时,邮箱为满

如果邮箱已经为满。进程就不能再往邮箱中存放信息,直到邮箱中的信息被取走,邮箱不再为满

  • Mailbox是SV内建的类,提供以下方法:

创建邮箱:new()

将信息放入邮箱:put()

非阻塞性将信试着放入邮箱: try_put()

从邮箱中取出信息:get()或peek()

非阳塞性从邮箱中取出信息:try_get()或 try_peek()

获取邮箱中的信息的数量:num()

 

写在最后:冲冲冲

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杰之行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值