0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

SV线程的使用和控制

jf_GctfwYN7 来源:IC修真院优秀学员 2023-10-21 17:30 次阅读

1、线程的使用

1.1程序和模块

• module (模块)作为SV从Verilog继承过来的概念,自然地保持了它的特点除了作为RTL模型的外壳包装和实现硬件行为, 在更高层的集成层面,模块之间也需要通信和同步。

• 对于硬件的过程块,它们之间的通信可理解为不同逻辑/时序块之间的通信或者同步,是通过信号的变化来完成的。

• 从硬件实现的角度来看,Verilog通过always,initial过程语句块和信号数据连接实现进程间通信。

• 我们可以将不同的module作为独立的程序块,他们之间的同步通过信号的变化(event触发)、等待特定事件(时钟周期)或者时间(固定延时)来完成。

如果按照软件的思维理解硬件仿真,仿真中的各个模块首先是独立运行的线程(thread)。

模块(线程)在仿真一开始便并行执行, 除了每个线程会依照自身内部产生的事件来触发过程语句块之外, 也同时依靠相邻模块间的信号变化来完成模块之间的线程同步。

• 线程即独立运行的程序。

• 线程需要被触发, 可以结束或者不结束。

• 在module中的initial和always,都可以看做独立的线程,它们会在仿真0时刻开始,而选择结束或者不结束。

• 硬件模型中由于都是always语句块 , 所以可以看成是多个独立运行的线程, 而这些线程会一直占用仿真资源, 因为它们并不会结束。

• 软件测试平台中的验证环境都需要由initial语句块去创建, 而在仿真过程中, 验证环境中的对象可以创建和销毁, 因此软件测试端的资源占用是动态的。

软件环境中的initial块对语句有两种分组方式 , 使用begin ... end或fork... join。

begin ... end的语句以顺序的方式执行,而fork...join中的语句则以并发方式执行。

与fork... join类似的并行方式语句还包括fork...join_any,fork...join_none.

• 线程的执行轨迹是呈树状结构的, 即任何的线程都应该有父线程。

• 父线程可以开辟若干个子线程, 父线程可以暂停或者终止子线程。

• 当子线程终止时, 父线程可以继续执行。

• 当父线程终止时, 其所开辟的所有子线程都应当会终止。

2、线程的控制

2.1 fork.... join

//fork...join
initial 
begin 
    $display("@%0t:start fork... join example", $time); 
    #10 $display("@%0t:sequential after #10", $time);
fork
    $display("@%Ot: parallel start", $time); 
    #50 $display("@%0t:parallel after #50", $time); 
    #10 $display("@%0t: parallel after #lO", $time);
begin
    #30 $display("@%0t:sequential after #30", $time); 
    #10 $display("@%0t:sequential after #10", $time);
end 
join 
    $display ("@%0t:after join", $time);
    #80 $display("@%0t: finish after #80", $time);
end
498856c2-6fe7-11ee-939d-92fbcf53809c.png  

打印代码:

@0: start fork... join example

@10: sequential after #10

@10: parallel start

@20: parallel after #10

@40: sequential after #30

@50: sequential after #10

@60: parallel after #50

@60: after join

@140: finish after #80

2.2 fork...join_any

//fork...join_any
initial 
begin 
    $display("@%0t:start fork... join_any example", $time); 
    #10 $display("@%0t:sequential after #10", $time);
fork
    $display("@%Ot: parallel start", $time); 
    #50 $display("@%0t:parallel after #50", $time); 
    #10 $display("@%0t: parallel after #lO", $time);
begin
    #30 $display("@%0t:sequential after #30", $time); 
     #10 $display("@%0t:sequential after #10", $time);
end 
join_any
    $display ("@%0t:after join", $time);
    #80 $display("@%0t: finish after #80", $time);
end

打印代码:

@0: start fork... join_any example

@10: sequential after #10

@10: parallel start

@10: after join_any

@20: parallel after #10

@40: sequential after #30

@50: sequential after #10

@60: parallel after #50

@90: finish after #80

2.3 fork...join_none

//fork...join_none
initial 
begin 
    $display("@%0t:start fork... none example", $time); 
    #10 $display("@%0t:sequential after #10", $time);
fork
    $display("@%Ot: parallel start", $time); 
    #50 $display("@%0t:parallel after #50", $time); 
    #10 $display("@%0t: parallel after #lO", $time);
begin
    #30 $display("@%0t:sequential after #30", $time); 
    #10 $display("@%0t:sequential after #10", $time);
end 
join_none
    $display ("@%0t:after join_none", $time);
    #80 $display("@%0t: finish after #80", $time);
end

打印代码:

@0: start fork... join_none example

@10: sequential after #10

@10: after join_none

@10: parallel start

@20: parallel after #10

@40: sequential after #30

@50: sequential after #10

@60: parallel after #50

@90: finish after #80

2.4 等待所有衍生线程

• 在SV中, 当程序中的initial块全部执行完毕, 仿真器就退出了。

• 如果我们希望等待fork块中的所有线程执行完毕再退出结束initial块, 我们可以使用wait fork语句来等待所有子线程结束。

task run_threads;
...
fork
check_trans(trl); //线程1 
check_trans(tr2); //线程2 
check_trans(tr3); //线程3
join_none
...
//等待所有fork中的线程结束再退出task 
wait fork;
endtask

2.5 停止单个线程

在使用了fork.. join_any或者fork... join_none以后,我们可以使用disable来指定需要停止的线程。

parameter TIME_OUT = 1000; 
task check_trans{Transaction tr);
fork
begin
//等待回应,或者达到某个最大时延
fork: timeout_block
begin
wait(bus.cb.addr == tr.addr);
$display("@%0t: Addr match %d", $time, tr.addr);
end 
#TIME_ OUT $display ("@%0t:Error: timeout, $time);
join_any 
disable timeout_block;
end
join_none
endtask

2.6 停止多个线程

disable fork可以停止从当前线程中衍生出来的所有子线程。

initial begin 
check_trans(trO); //线程0
//创建一个线程来限制disable fork的作用范围 
fork//线程1
begin
check_trans(trl); //线程2 
fork//线程3
check_trans(tr2); / /线程4
join 
//停止线程1-4, 单独保留线程0 
#(TIME_OUT/2) disable fork
end
join
end
499c3a8e-6fe7-11ee-939d-92fbcf53809c.png

2.7 停止被多次调用的任务

如果你给某—个任务或者线程指明标号, 那么当这个线程被调用多次以后 , 如果通过disable去禁止这个线程标号, 所有衍生的同名线程都将被禁止。

task wait_for_time_out(int id);
if (id == 0)
fork
begin
#2; 
$display("@%0t:disable wait_for_time_out"' $time); 
disable wait_for_time_out;
end 
join_none 
fork : just_a_little
begin
$display ("@%0t:%m: %0d entering thread", $time, id); 
#TIME_OUT; 
$display("@%0t:%m: %0d done", $0ime, id); 
end
join_none
endtask
initial begin
wait_for_time_out(0); // Spawn thread 0 
wait_for_time_out(1); // Spawn thread 1  
wait_for_time_out(2); // Spawn thread 2 
#(TIME_OUT*2) $display("@%0t:All done", $time); 
end

• 任务wait_for_time_out被调用了三次, 从而衍生了三个线程。

• 线程0在#2延时之后禁止了该任务,而由于三个线程均是“ 同名”线程, 因此这些线程都被禁止了, 最终也都没有完成。

内容来源:IC修真院优秀学员

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Verilog
    +关注

    关注

    28

    文章

    1351

    浏览量

    110066
  • 时钟
    +关注

    关注

    10

    文章

    1732

    浏览量

    131437
  • RTL
    RTL
    +关注

    关注

    1

    文章

    385

    浏览量

    59752
  • 程序
    +关注

    关注

    117

    文章

    3782

    浏览量

    80990
  • 线程
    +关注

    关注

    0

    文章

    504

    浏览量

    19674

原文标题:IC学霸笔记 | SV线程

文章出处:【微信号:IC修真院,微信公众号:IC修真院】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    HDMI+AV+SV转HDMI、AV+SV转HDMI转换器芯片方案

    HDMI+AV+SV转HDMI、AV+SV转HDMI转换器芯视音HDMI+AV+SV转HDMI产品可将一路HDMI信号+一路CVBS信号+一路S-VIDEO信号转成HDMI信号。输入端不管输入PAL
    发表于 09-29 16:49

    双路400mA LED分段调色温专用芯片方案 SV420/SV425

    420/SV4253,方案特点 SV420/SV425是双路LED色温控制专用芯片,支持40V直接输入工作电压,简化输入限压电阻设计,提高可靠性。 方案仅在变压器次级即可自动完成上下电
    发表于 07-03 17:31

    DY-SV5W模块介绍

    以下为DY-SV5W介绍摘抄模块应用手册1.产品概述DY-SV5W是本司自主研发的一款智能语音模块,集成IO分段触发,UART串口控制,ONE_line单总线串口控制,标准MP3等7种
    发表于 02-10 06:25

    sv810是什么?sv810有何功能呢

    sv810是什么?sv810有何功能呢?
    发表于 03-03 07:07

    Linux线程实现与线程控制步骤简析

    处理。因此,大大减少了上下文切换的开销。同进程一样,线程也将相关的变量值放在线程控制表内TCB。一个进程可以有多个线程,也就是有多个线程控制表及堆栈寄存器,但却共享一个用户地址空间。要
    发表于 04-25 09:29

    Java的线程课程

    线程的概念线程其实是控制线程(Thread of control)的简写。 控制线程就是程序运行时的路径,是在一个程序中与其它控制线程无关的
    发表于 04-10 15:58 0次下载

    创维SV-666S SV-767S功放电路图

    创维SV-666S SV-767S功放电路图
    发表于 05-19 16:42 94次下载
    创维<b class='flag-5'>SV</b>-666S <b class='flag-5'>SV</b>-767S功放电路图

    SV8300功能介绍

    SV8300SV8300的可堆叠式机架设计支持在一个系统内服务器功能、媒体网关和媒体转换等功能的集成。
    发表于 02-10 15:11 25次下载
    <b class='flag-5'>SV</b>8300功能介绍

    如何在基于SV的仿真环境中使用软件语言

    除了这个方式,SV还提供了和C/C++直接的接口DPI。DPI接口允许用户用C编写程序,并和SV实现对接,也可以用SV写程序,将SV程序导出到c中。
    的头像 发表于 09-27 14:20 3190次阅读
    如何在基于<b class='flag-5'>SV</b>的仿真环境中使用软件语言

    Arduino串口控制DY-SV5W音频播放

    以下为DY-SV5W介绍摘抄模块应用手册1.产品概述DY-SV5W是本司自主研发的一款智能语音模块,集成IO分段触发,UART串口控制,ONE_line单总线串口控制,标准MP3等7种
    发表于 12-06 19:21 24次下载
    Arduino串口<b class='flag-5'>控制</b>DY-<b class='flag-5'>SV</b>5W音频播放

    网络广播对讲编码解码模块SV-2101V/SV-2103V介绍

    模块结构 SV-2101V/SV-2103V使用了AT32F437VGT7处理器构架加专业的双向音频Codec编解码器,处理器负责数据的传输,用户命令的解析执行以及功放接口的控制,专业音频Codec
    发表于 02-14 09:52 697次阅读

    核心线程数和最大线程数区别

    达到最大线程数。当任务执行完毕后,线程池会根据线程池参数来决定是否回收线程。 简单来说,核心线程数用于优化
    的头像 发表于 06-01 09:33 7648次阅读

    线程池的线程怎么释放

    线程分组看,pool名开头线程占616条,而且waiting状态也是616条,这个点就非常可疑了,我断定就是这个pool开头线程池导致的问题。我们先排查为何这个线程池中会有600+的
    发表于 07-31 10:49 2269次阅读
    <b class='flag-5'>线程</b>池的<b class='flag-5'>线程</b>怎么释放

    核心线程数和最大线程数怎么设置

    核心线程数和最大线程数是Java线程池中重要的参数,用来控制线程池中线程的数量和行为。正确地设置这两个参数可以优化系统的性能和资源利用率。本
    的头像 发表于 12-01 13:50 9022次阅读

    表面贴装压控晶体振荡器 DSV221SV DSV321SV :精准频率控制的卓越之选

    表面贴装压控晶体振荡器(DSV221SV/DSV321SV):精准频率控制的卓越之选
    的头像 发表于 08-06 13:44 274次阅读
    表面贴装压控晶体振荡器 DSV221<b class='flag-5'>SV</b> DSV321<b class='flag-5'>SV</b> :精准频率<b class='flag-5'>控制</b>的卓越之选