SV中的线程

SV中线程之间的通信可以让验证组件之间更好的传递transaction。

SV对verilog建模方式的扩展:1) fork.....join 必须等到块内的所有线程都执行结束后,才能继续执行块后的语句。(所以使用的很少)

                                       2) fork.....join_none 先执行块后的线程,而后再执行块内的线程。不会产生块后的线程必须等块内线程的情形。

                                       3) fork.....join_any 只要块内的线程有一个执行结束,就执行块之后的线程。

 

需要说明一下,begin.....end之间的顺序操作,只要先前的进程已经开始执行,那之后的进程就会开始执行。在2例中a = b线程先于c = a线程执行,但俩者都是在

                    零时刻执行,因为阻塞赋值都是一个仿真时间区域,所以最后的结果是c = b;如果改成a <= b;因为同一个仿真时刻,阻塞赋值在非阻塞赋值之前,所

                    以最后的结果是c = a; a <= b; (未仿真检测)

                    在例1中,0时刻a = b线程被#2阻塞,c=a线程因为a = b还未执行结束也阻塞。2个仿真单位之后,a=b线程结束,开始c = a线程,被#3阻塞,又

                    过3个仿真单位后,执行结束。

                      begin                                       begin

                            #2  a = b;                                a = b;

                            #3  c = a;                                c = a;

                      end                                          end

 

线程中的自动变量:两种用法,#0会阻塞$display任务,而让for循环在仿真时刻0时,就先于$display执行好。

                    initial  begin                                                   initial  begin

                                   for(int j=0;j<3;j++)                                      for(int j=0;j<3;j++)   begin

                                       fork                                                                  int k = j;

                                          automatic  int k = j;                                           fork

                                          $write(k);                                                             $write(k);            

                                       join_none                                                              join_none   end

                                   #0$display;                                                  #0$display;

                               end                                                              end

停止一个线程:

task  check_trans(Transaction  tr);

                   fork    begin

                                 fork:time_out

                                             begin

                                                 wait(bus.cb.addr == tr.addr);

                                                 $display("@%0t:Address Match", $time);

                                             end

                                             #TIME_OUT $display("@%0t:Error", $time);

                                 join

                   join_any

                   disable time_out               //进程块名

endtask

 

事件通信:1)同verilog一样的,@, ->操作符,边沿阻塞。因为event是零脉冲,所以这种方式,当->在@之前时,同一个event不能被发现触发。

                  ->>在nonblocking的区域执行触发

              2)SV扩展的电平检测triggered()函数。wait(e1.triggered()),在当前时间的最后执行,保证如果当前时间有触发,则不会引起阻塞

在验证经常将event参数放在类的new的参数列表中,同mailbox一样,之后会说到。这样方便直接在顶层通过event或mailbox连接构件。

 

旗语互斥访问:semaphore来创建,new函数构建,put获得一个,get得到一个,得不到或放不进时,阻塞进程。try_get(),同get但是不会被阻塞。

 

邮箱通信:mailbox来创建,new函数来构建,put移出数据,get移入数据,peek对FIFO数据的copy不会移入移出。mailbox内存放的是句柄不会是对象。

    mailbox默认都是typeless的,这样在producer和consumer之间,可能会出现类型出错的情况,这样只能在run_time中发现错误;

    使用参数化的mailbox,可以在compile的时候,就发现在这个问题;

    local static mailbox #(uvm_phase) m_phase_hopper = new();  只接受phase类型的指针;

    mailbox内自定义的函数,num(),put()/try,get/try()

        class Generator;                                                                         class Driver;

                   Transactin tr;                                                                              Transactin tr; 

                   mailbox mbx;                                                                              mailbox mbx;

                   function new(mailbox mbx)                                                          function new(mailbox mbx)

                                  this.mbx = mbx;                                                                           this.mbx = mbx;    

                   endfunction                                                                                 endfunction

                   task run(int count);                                                                      task run(int count);                  

                                   repeat(count)  begin                                                                   repeat(count)  begin

                                             tr = new();                                                                      mbx.get(tr);

                                             assert(tr.randomize);                                                        ........

                                             mbx.put(tr);                                                                     ..........

                                   end

                   endtask                          

         endclass                                                                                     endclass

         program automatic mailbox_example(arbif......)

                   'include "Generator.sv"

                   'include "Driver.sv"

                   'include "Transaction.sv"

                   mailbox  mbx;

                   Generator   gen;

                   Driver    drv;

                   int  count;

                   initial  begin

                                 count = $urandom_range(50);

                                 mbx = new();

                                 gen = new(mbx);         //gen与drv同一个mailbox来传递transaction

                                 drv = new(mbx);

                                 ......................

                             end

转载于:https://www.cnblogs.com/-9-8/p/4422466.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值