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

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

3天内不再提示

SystemVerilog中线程常用的精细化控制方法

sanyue7758 来源:硅芯思见 2023-03-27 10:48 次阅读

在计算机中存在进程和线程的概念,其中进程是并发执行的程序在执行过程中分配和管理资源的基本单位,线程是进程的一个执行单元,是比进程还要小的独立运行的基本单位。在一个程序中至少有一个进程,一个进程至少有一个线程。进程是资源分配最小单位,线程是程序执行的最小单位。

计算机在执行程序时,会为程序创建相应的进程,进行资源分配时,是以进程为单位进行相应的分配。每个进程都有相应的线程,在执行程序时,实际上是执行相应的一系列线程,过程如下图所示。

0aa22f40-cb29-11ed-bfe3-dac502259ad0.png

在SystemVerilog中,虽然IEEE中也使用了process和thread,但是在实际手册解释的过程中,两个概念基本上处于互用的状态,所以本文统一使用线程进行描述说明SystemVerilog中线程常用的精细化控制方法。

在SystemVerilog中,线程的创建主要有以下几种方式:

Ø每一个initial结构都会创建一个对应的线程;

Ø每一个final结构都会创建一个对应的线程(关于final用法参考《SystemVerilog中的final是怎么结束的》);

Ø每一个always、always_comb、always_latch和always_ff结构都会创建对应的线程;

Øfork-join(join_any/join_none)结构中每条并行执行的语句块;

Ø每一个动态线程,一般并行执行的线程并且不会阻塞其他线程或者task中其他语句执行的线程;

Ø每一个连续赋值语句;

0ab709c4-cb29-11ed-bfe3-dac502259ad0.png

在SystemVerilog中可以通过process来实现对于上述线程的控制,而这个process其实是SystemVerilog中的一个内建类,通过该类声明的句柄可以指向特定的线程,从而可以通过该句柄实现对于指向线程的访问控制。process类在SystemVerilog中的定义如下:

0ac638e0-cb29-11ed-bfe3-dac502259ad0.png

虽然process是一个类,但是这哥们比较特殊,不能被拓展派生,也就是说process不会有子类的,并且该类在创建对象时,是不能使用new函数的,process类型句柄指向对象是通过process::self()完成的,因此如果用户需要通过process句柄指向对应的线程时需要在对应的线程中调用process::self()实现。在process中经常用来实现对于线程控制的方法主要如下:

Øself()返回指向当前线程的句柄;

Østatus()返回当前句柄指向线程的状态(包含的状态有:FINISHED、RUNNING、WAITING、SUSPEND和KILLED等状态);

Økill()终止当前句柄指向的线程及其开启的所有子线程;

Øawait()等待调用其的句柄指向的线程执行完成,注意不能在调用其的句柄指向的线程中使用该方法,只能在别的线程中调用该方法用以阻塞调用该方法的句柄指向的线程;

Øsuspend()挂起当前句柄指向线程;

Øresume()恢复被挂起的线程;

Øsrandom()设置线程的随机种子;

上述方法中,kill()、await()、suspend()、resume()只能用于initial、always和fork结构启动的线程。下面将针对process中这些方法的使用进行示例说明。

【示例】

0ad44962-cb29-11ed-bfe3-dac502259ad0.png

仿真结果】

0aefeb40-cb29-11ed-bfe3-dac502259ad0.png

示例中,首先声明了两个句柄p1和p2,在两个initial结构中,p1和p2通过调用“process::self()”实现p1和p2分别指向其所在的initial结构开启的线程。

第一个initial结构中“@0”时刻第一个$display中通过p1.status()方法获取了当前线程的状态(log中显示为RUNNING),然后等待10个时间单位后,再次调用$display(),在其中调用p1.status()方法获取了当前线程时刻“@10”的状态(log中显示为RUNNING),再经过100个时间单位,在时刻@110再次在$display()中调用p1.status()方法获取了当前线程的执行状态(log中显示为RUNNING),该语句执行完后第一个initial结构开启的线程执行完毕。

第二个initial结构中,“@0”时刻第一个$display中通过p2.status()方法获取了当前线程的状态(log中显示为RUNNING),然后等待10个时间单位后,再次调用$display(),在其中调用p2.status()方法获取了当前线程时刻“@10”的状态(log中显示为RUNNING),然后通过p1调用await()方法,p1.await()后的语句将处于等待p1指向线程执行完毕,其后的语句此时处于阻塞的状态,当p1指向的线程(也就是第一个initial结构)在时刻“@110”执行完毕,p1.await()不再阻塞其后语句的执行,其后的语句继续执行,此时调用p1.status()显示的值为p1当前的状态(log中显示此时p1状态位FINISHED)。在等待100个时间单位,在时刻“@210”调用p2.status()时,p2指向的线程还没有执行完毕,所以其显示的状态仍为RUNNING。上述两个线程执行的过程如下图所示。

0b00d31a-cb29-11ed-bfe3-dac502259ad0.png

【示例】

0b0ed384-cb29-11ed-bfe3-dac502259ad0.png

【仿真结果】

0b24aa10-cb29-11ed-bfe3-dac502259ad0.png

示例中,声明了三个process句柄p1、p2和p3.在initial结构中调用“process::self()”实现p1指向当前的initial结构开启的线程,然后调用$display语句通过p1.status()获取当前initial结构开启线程的执行状态为RUNNING(该initial结构正在执行中)。

fork-join_none结构中所有语句是并行执行的,示例中的fork结构中一共有三个线程,

第一个线程通过调用“process::self()”实现p2指向自己,当该方法结束后,该线程的历史使命也就结束了,这里需要注意p2并没有指向fork。

第二个线程为一个begin-end结构,在begin-end中首先通过调用“process::self()”实现了p3指向该线程,然后调用$display中通过p3.status()获取当前线程执行状态为RUNNING(该begin-end结构还在执行中),在等待100个时间单位,通过p2.status()和p3.status()获取当前时刻p2和p3指向线程的执行状态,因为p2指向的线程在调用“process::self()”完后就执行完了,所以p2.status()返回的状态位FINISHED,p3.status()获取的状态值仍为RUNNING(其所指向begin-end结构还在执行中),再等待100个时间单位,通过p2.status()和p3.status()获取当前时刻p2和p3指向线程的执行状态,因为此时fork-join_none中并行执行的第三个线程通过p3调用了kill()方法,所以begin-end结构对应的线程被kill掉,因此此时企图在等待100个时间单位再次获取p2和p3执行状态的语句不会执行。

第三个线程为等待190个时间单位后调用p3.kill(),实现了对于fork-join_none中第二个线程的kill操作。

fork-join_none结构后通过p1.status()获取p1指向线程的执行状态为RUNNING(因为p1指向的initial结构正在执行中);

在经过10个时间单位,通过p2.status()和p3.status()获取当前时刻p2和p3指向线程的执行状态分别为FINISHED(p2指向线程已经执行完毕)和WAITING(p3指向线程正在执行其中#100,处于延迟阻塞等待状态);

通过p2.kill()企图kill掉p2指向的线程,实际上此时p2指向的线程已经执行完毕,所以并不会影响p2指向线程的状态,所以此时在p2.kill()后通过p2.status()和p3.status()获取当前时刻p2和p3指向线程的执行状态仍为FINISHED(p2指向线程已经执行完毕)和WAITING(p3指向线程还在执行其中#100,处于延迟阻塞等待状态);

在经过210个时间单位,通过p1.status()、p2.status()和p3.status()获取当前时刻p1、p2和p3指向线程的执行状态为RUNNING(p1指向的initial结构正在执行中)、FINISHED(p2指向线程已经执行完毕)和KILLED(p3指向的线程执行完之前,在fork-join_none结构中等待190个时间单位时已经被kill掉了,所以此时状态位KILLED);上述线程执行过程如下图所示。

0b31298e-cb29-11ed-bfe3-dac502259ad0.png

【示例】

0b3d0aec-cb29-11ed-bfe3-dac502259ad0.png

【仿真结果】

0b4ecdea-cb29-11ed-bfe3-dac502259ad0.png

示例中,p通过“process::self()”指向了当前的线程,通过$display显示了p.status()为RUNNING,等待100个时间单位,企图通过p.status()显示p的状态,但是在这100个时间单位等待到其中的20个时间单位时,另外一个initial结构中仿真开始等待的20个时间单位后调用了p.suspend(),即此时将p指向的线程挂起,所以此时p指向的线程这时处于挂起等待状态,$display显示了p.status()为SUSPEND,在再等待30个时间单位,调用p.resume()将之前挂起的p指向的线程返回,因为当前线程并未阻塞,所以当前线程继续执行,$display显示了p.status()为WAITING,当前initial执行完后,p指向的线程再次开始继续之前暂停的执行。

再等待80个时间单位(之前100个时间单位计时20个时间单位后还剩下80个时间单位未计时)调用$display显示了p.status()为RUNNING,再等待100个时间单位后调用$display显示了p.status()仍为RUNNING。上述线程执行过程如下图所示。

0b5c5ac8-cb29-11ed-bfe3-dac502259ad0.png

通过示例可以看到,await是用来等待一个线程执行完成后返回的,而suspend则用来将一个线程手动挂起,其解除必须通过resume()来完成,并不一定要等到线程执行完毕。

上述通过示例展示了process中常用方法的使用,其实在UVM中对于线程的控制大多都是通过process完成的,如下例中run_phase的执行。

0b725e7c-cb29-11ed-bfe3-dac502259ad0.png

当我们执行run_test时,实际上在run_test这个task中声明了一个process句柄phase_runner_proc,这个句柄在425行通过“process::self()”指向了当前fork-join_none结构中的一个线程,这个线程就是fork-join_none中的begin-end。当后续的m_run_phases()执行完成后,wait等到了m_phase_all_done拉高,表明当前的run_phases执行完毕,然后通过phase_runner_proc.kill()将fork-join_none中开启的线程及其所有子线程都kill掉,相当于打扫战场,从而通过process实现了对于fork-join_none中线程及其所有子线程的控制操作。





审核编辑:刘清

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

    关注

    19

    文章

    7493

    浏览量

    87925
  • Verilog
    +关注

    关注

    28

    文章

    1351

    浏览量

    110091
  • UVM
    UVM
    +关注

    关注

    0

    文章

    182

    浏览量

    19169

原文标题:进程(线程)精细化控制中方法的使用

文章出处:【微信号:处芯积律,微信公众号:处芯积律】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    [原创] 欧洲精细化工展览会(ChemSpec Europe 2010)

      欧洲精细化工展览会(ChemSpec Europe 2010)      展会时间
    发表于 02-26 13:52

    2010年迪拜精细化工展

    ,Chemspec India 成功举办之后,精细化工展又一次开辟新市场,成为目前中东地区唯一一个针对精细化工的专业展会。市场介绍中东主要包括阿联酋、科威特、沙特、伊拉克、伊朗、也门、阿曼、巴林、卡塔尔、叙利亚
    发表于 06-02 17:26

    2010迪拜精细化工展/中东化工技术机械展

    Chemspec Europe,Chemspec India 成功举办之后,精细化工展又一次开辟新市场,成为目前中东地区唯一一个针对精细化工的专业展会。市场介绍中东主要包括阿联酋、科威特、沙特、伊拉克、伊朗
    发表于 06-29 13:57

    怎么才能让无线站点实现精细化覆盖?

    网络覆盖是电信运营商面临的最大难题。数据业务浪潮的到来,将带来新一轮的网络竞争,作为无线网络的神经元,站点更需要精细化覆盖到最细小的角落,应对多场景变化,并实现站址获取、快速交付、绿色环保、TCO节省等目标。
    发表于 08-14 07:41

    实用精细化工辞典

    实用精细化工辞典共收5000余条精细化工名称。所有名称按中文笔划、笔顺排列,检索方便。中文名称原为英文名称;外国商品名均采用原名称,但日文假名均以英文表示;单位一
    发表于 11-29 09:33 0次下载
    实用<b class='flag-5'>精细化</b>工辞典

    精细化常用原材料手册

    精细化常用原材料手册:介绍了精细化工产品制造常用原材料919种,分为36类:酸、碱、油、脂、羊毛脂及其衍生物,蜡,溶剂,表面活性剂,合成树脂,合成橡胶及弹性体,单
    发表于 11-30 11:17 0次下载
    <b class='flag-5'>精细化</b>工<b class='flag-5'>常用</b>原材料手册

    无线站点精细化覆盖

    网络覆盖是电信运营商面临的最大难题。数据业务浪潮的到来,将带来新一轮的网络竞争,作为无线网络的神经元,站点更需要精细化覆盖到最细小的角落,应对多场景变化,并实现站
    发表于 04-29 12:22 901次阅读

    基于UEMS的电力系统精细化稳定控制系统

    基于UEMS的电力系统精细化稳定控制系统_常乃超
    发表于 01-04 17:05 0次下载

    MES系统实行精细化管理的六大步骤

    本文主要介绍了MES系统实行精细化管理的六大步骤。
    发表于 06-04 08:00 4次下载

    如何才能实现smt贴片车间的精细化管理

    要实现smt贴片车间的精细化管理,如果还是靠之前那种表格传达数据的模式必然会出现衔接不良或者效率底下的问题,现在市场上已经出现了ERP和更全面的MES系统,如果从精细化的角度来讲,应该要把生产步骤
    发表于 09-28 14:25 1871次阅读

    福斯特、光华科技、西陇科学上榜2020中国精细化工百强企业榜单

      11月25日,“第二十届国际精细化工原料及中间体峰会暨2020中国精细化工百强发布会”在山东寿光举行,杭州福斯特应用材料有限公司、西陇科学股份有限公司、广东光华科技股份有限公司荣登“2020中国
    的头像 发表于 12-15 15:22 4773次阅读

    基于TransModeler软件的精细化交通设计

    作为“区域—宏观—中观—微观”一体化模型体系的中观交通模型,以面向片区精细化交通改善设计和交通影响评价为出发点,采用“静态动态分配相结合、整体中观局部微观”的建模方法,平衡建模效率与精度,实现精细化交通设计各类指标评估。
    的头像 发表于 08-20 12:34 1873次阅读

    进程(线程)精细化控制方法的使用

    在计算机中存在进程和线程的概念,其中进程是并发执行的程序在执行过程中分配和管理资源的基本单位,线程是进程的一个执行单元,是比进程还要小的独立运行的基本单位。在一个程序中至少有一个进程,一个进程至少有
    的头像 发表于 03-26 14:27 581次阅读

    浅谈数据中心精细化建设策略分析

    摘要:通过分析用户需求、建设和运维等多方对数据中心建设的要求;结合国家政策、数据中心发展趋势,创新性地引入关键因素多角度分析法。同时系统性地提出数据中心高质量发展中如何进行精细化建设的策略。
    的头像 发表于 05-17 10:24 700次阅读
    浅谈数据中心<b class='flag-5'>精细化</b>建设策略分析

    综合管廊精细化节能系统设计与实施

    的基础数据,利用建立的能耗统计数据库、管廊能耗评价指标体系,研发一套管廊精细化节能诊断系统,主要目标是实现对综合管廊能耗精细化分析,节约地下综合管廊运维过程中的能耗,为运维管理人员提供决策支持、节能诊断和运行策
    的头像 发表于 06-19 16:31 357次阅读
    综合管廊<b class='flag-5'>精细化</b>节能系统设计与实施