专栏首页ICSOC.TECH【011】Verilog Task Concurrent Activation

【011】Verilog Task Concurrent Activation

最近做一个模块级的仿真,需要在两个过程中反复调用同一个Task。这种场景还是比较常见的,比如一个过程作为普通的配置过程,一个作为中断服务过程,这个Task可以是寄存器读或写。在某些Case下,发现该Task的防止并发执行的逻辑并不能正常工作。于是做了些阅读和实验,弥补了一下自己在Task并发执行上的知识漏洞。

先来个不符合预期的例程和运行结果。

从运行结果可以看到,task<1>、<2>、<3>均没有正常结束,都被task<4>覆盖掉了。什么原因呢?在Verilog标准IEEE.1363-2005里有这样的解释:

All variables of a static task shall be static in that there shall be a single variable corresponding to each declared local variable in a module instance, regardless of the number of concurrent activations of the task. Variables declared in static tasks, including input, output, and inout type arguments, shall retain their values between invocations.

对应上述的例程,就是在static task test中,输入端口id这个参数是静态的,无论task被调用多少次,只保留一份参数。所以参数的最终取值决定于最后一次调用时传入的值。这样就可以理解为什么每次结束时,打印出的id都是4了。

如何解决这种并发性调用,有两个思路。一个思路是建立一个类似Command FIFO的机制,每个过程中对task的调用都往同一个FIFO里写,然后按FIFO的出口顺序执行。这样似乎从逻辑上根本上解决了并发的问题,回避了Verilog的语法解释问题。另一个思路就是Verilog标准提供的Automatic Task,在标准中是这样描述的:

All variables of an automatic task shall be replicated on each concurrent task invocation to store state specific to that invocation.

就是Verilog自动为task的每次调用分配独立的变量空间,做到互不干扰。

下面是采用第二种思路的例程和运行结果。

代码中,只有第33行有变动,添加了automatic关键字。

运行结果却完全不同,对task的四次调用都互不干扰了。但是也注意到task<2>、<3>、<4>的执行顺序却和调用顺序不同,应该容易理解,这是task调用的栈机制导致的。把task<2>、<3>、<4>压入栈,出栈时顺序自然相反了。

这也说明,只依靠Verilog自身的语法,对于并发性的控制是不理想的,有时甚至是完全不符合预期的。还是需要从逻辑上来根本解决。

在Verilog标准中,还提到:

However, static tasks in different instances of a module shall have separate storage from each other.

现在进一步实验,先把之前的task放入一个module中,这样test_num、test_busy就成了该module的instance之间独立的变量。

然后在testbench中例化两次这个module,并分别调用这两个module instance中的相同task。

运行结果也证明了这点,test_num在module instance之间独立变化。只不过因为仍是static task,所以每个module的多次task调用存在覆盖的问题。

把static task改为automatic task后的运行结果如下,符合期望。但是出栈顺序导致执行顺序与调用顺序不符。

很有意思,对吧?

最后附上标准中的一段话作为结尾。

The keyword automatic declares an automatic task that is reentrant with all the task declarations allocated dynamically for each concurrent task entry. Task item declarations can specify the following:

  • Input arguments
  • Output arguments
  • Inout arguments
  • All data types that can be declared in a procedural block

本文分享自微信公众号 - icsoc(ic-soc),作者:韩京飞

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2016-12-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 增强tclsh的行编辑功能

    IC 设计这行的很多 EDA 工具都内嵌了tcl 解释器,所以日常工作免不了和 tcl 语言打打交道。如果想写两句 tcl 代码做个测试,当然可以新建一个脚本文...

    icsoc
  • 芯片做出来有bug怎么办

    不说一颗芯片tape out前的各种惊心动魄,相比拿到样品后测试时的心潮起伏,到底哪个更刀刀催人老;也不说测试报告的issue到底是feature还是bug;更...

    icsoc
  • 房贷利率基于LPR浮动的简单计算

    相信过不了多久,广大房奴就会收到贷款银行的要求调整贷款协议的电话。因为中国人民银行(央行)2019年30号公告[1]要求2020年8月底前完成存量贷款浮动利率的...

    icsoc
  • 从Promise来看JavaScript中的Event Loop、Tasks和Microtasks

    本文采用Creative Commons BY-NC-ND 4.0(自由转载-保持署名-非商用-禁止演绎)协议发布。

    Fundebug
  • linux命令行todo列表管理工具Taskwarrior介绍

    Taskwarrior 是一款在命令行下使用的TODO列表管理工具,或者说任务管理工具,灵活,快速,高效。

    zqb_all
  • C++任务队列与多线程

    摘要:       很多场合之所以使用C++,一方面是由于C++编译后的native code的高效性能,另一方面是由于C++优秀的并发能力。并行方式有多进程 ...

    知然
  • Android 学习笔记思考篇

    Android 系统从 2008 年正式发布到现在已经过去了 11年,系统版本也来到了 10,作为开发者,或者作为用户,我们见证了系统一次次大大小小的改动,见证...

    Android架构
  • Linux常用命令:top

    linjinhe
  • [spark] Task成功执行的结果处理

    在文章Task执行流程 中介绍了task是怎么被分配到executor上执行的,本文讲解task成功执行时将结果返回给driver的处理流程。

    UFO
  • Spring TaskScheduler实现定时任务分析

    实际上还是ThreadPoolTaskScheduler的方法,只是封装了一层更适合项目使用

    深雾

扫码关注云+社区

领取腾讯云代金券