前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SystemVerilog线程控制与通信

SystemVerilog线程控制与通信

作者头像
数字芯片社区
发布2020-07-20 16:01:52
1.1K0
发布2020-07-20 16:01:52
举报
文章被收录于专栏:数字芯片数字芯片

01

线程控制

1.概述

线程,即独立运行的程序;

线程需要被触发执行,可以结束或者不结束;

  • 在module中的initial和always,都可以看作独立的线程,他们在仿真0时刻开始,而选择结束或者不结束;
  • 在硬件模块中都是always语句块,所以可以看成是独立运行的线程,而且会一直占用仿真资源,因为他们不会结束;

验证环境需要initial语句块,在仿真过程中,验证环境中的对象可以创建和销毁,故验证环境的资源是动态的;

  • 验证环境中的initial语句块有两种方式:begin……end或者fork……join;

Begin……end中语句顺序执行,而fork……join中语句并发执行;

与fork……join类似的并行语句有fork……join_any、fork……join_none;

  • 线程的执行轨迹是呈树状结构,即任何线程都应该有父线程;
  • 父线程可以开辟若干子线程,父线程可以暂停或者终止子线程;
  • 当子线程终止时,父线程可以继续执行;
  • 当父线程终止时,其子线程都终止执行;

2.并行线程

fork……join需要所有并行线程都结束才会继续执行;

fork……join_any其中任意一个线程结束就继续执行;

fork……join_none不等待子线程,直接继续执行;

  • 注意:

Fork……join_any和fork……join_none继续执行后,其一些未完成的子线程仍将继续在后台执行;

如果要等待或者停止这些子线程,可使用wait fork 或者disable fork;

代码语言:javascript
复制
task do_test;
    fork
        ……
    join_any
    fork
        ……
    join_none
    wait fork;//等待所有子线程结束
endtask
代码语言:javascript
复制
task get_first(output ubt adr);
    fork
        ……
    join_any
    disable fork;
endtask

3.时序控制

  • SV可以通过延迟控制或者事件(event)等待来完成时序控制;

延迟控制即通过#来完成;

#100 clk2=clk1;

事件(event)控制即通过@来完成;

@a clk1=clk2; //等待事件

@(posedge clk)a=b;//边沿触发

Wait语句可以与事件或者表达式结合使用;

Real AOR[];

Initial wait(AOR,size()>0) //wait语句完成电平触发

02

线程同步

1.概述

测试平台所有线程都需要同步并进行交换数据;

一个线程等待另一个线程;

2.事件event

  • 通过event声明一个event变量,并且触发;
  • event变量可以由一端去触发,再由另一端完成阻塞式的等待,即可以用来控制多个线程之间的同步;
  • 通过->来触发事件;
  • 其他等待该事件的线程可以通过@操作符或者wait()来检查事件触发状态来完成等待事件;
代码语言:javascript
复制
event done,blast;  //声明两个独立的事件
event done_too=done;   //事件done赋值给done_too
task trigger(event ev);
    ->ev;   //触发ev事件
endtask
……
fork 
    @done_too;  //等待done_too
    #1 trigger(done);  //触发done事件
join

fork
    ->blast;  //触发blast事件
    wait(blast.triggered);  //电平触发等待
join
  • wait_order() 可使得线程保持等待,直到在参数列表中的事件event按照顺序从左往右依次完成;
代码语言:javascript
复制
wait_order(a,b,c);

3.旗语(semaphore)

旗语是一个互斥体,使用旗语可以实现对同一资源的访问控制;

在创建旗语时,会为其分配固定的钥匙数量;

使用旗语的进程必须先获得钥匙,才可访问资源;

旗语的钥匙数量可以有多个,等待旗语的进程也可以有多个;

旗语的等待队列是先进先出(FIFO),即先排队等待旗语的将优先得到钥匙;

旗语操作

创建旗语

semaphore sm;//创建一个旗语

sm=new(1); //分配一个钥匙

创建一个固定钥匙数量的旗语:new

从旗语获取一个或多个钥匙(阻塞型):get

返回一个或多个钥匙:put

获取一个或多个钥匙而不被阻塞:try_get

代码语言:javascript
复制
task send;
    sem.get(1)  ///获取钥匙
   
     ……
    
    sem.put(1);  //处理完成时把钥匙返回
endtask

03

线程通信

1.信箱

用于收发信息,SV中信箱可以存放任何数据类型,也可以从信箱中读取这些数据,

创建信箱:new()

将信息写入信箱:put()

写入信箱但不会阻塞:try_put()

获取信息:get() 获取信息并取出数据:

peek()获取信息不会取出数据

从信箱获取数据但不会阻塞:try_get()/try_peek()

获取信箱信息数目:num()

2.信箱和队列区别

  • 信箱必须通过new()例化,队列只需要声明
  • 信箱的存取方法put()和get()是阻塞方法,不一定会立即返回;队列的存取方法push_back和pop_front()是非阻塞方法,会立即返回;
  • 传递形式参数时,如果是input方向,则信箱类型传递的是句柄,队列类型完成的是队列内容的拷贝;

3.总结

  • event:最小信息量的触发,即单一的通知单元,用来做事件的触发,也可多个事件组合起来作线程之间的同步;
  • semaphore:共享资源安全,用于多线程间需要对某一公共资源做访问;
  • mailbpx:SV类似FIFO,在线程之间做数据通信或者内部数据缓存;

END

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数字ICer 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.概述
  • 2.并行线程
  • 3.时序控制
  • 1.概述
  • 2.事件event
  • 3.旗语(semaphore)
  • 1.信箱
  • 2.信箱和队列区别
  • 3.总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档