1. 前言
本文讲一下SystemVerilog的time slot里的regions以及events的调度。SystemVerilog语言是根据离散事件执行模型定义的,由events驱动。SystemVerilog描述是由连接的执行thread或processes组成。Process是可衡量的,也具有状态,并且可以响应输入的变化以产生输出。Process是并发调度的元素,例如initial,process其实还包括了always, always_comb, always_latch, always_ff, contiguous assignment, asynchronous tasks和procedural assignment statement。
SystemVerilog是一种并行编程语言,我们需要重点了解哪些执行顺序对用户是有保证的,哪些执行顺序是不确定的。这块内容比较晦涩难懂,但要是理解了regions和events的调度,对我们写代码和调试会有极大的帮助,而且也更了解EDA工具的执行机制。
2. Event的定义
在仿真系统中net或variable的状态的任何更改,都被视为更新事件(update event)。Processes对upate event是敏感的。当一个update event发生时,所有对该event敏感的processes都会被当作以任意顺序进行评估。Process的评估也是一个event,称作评估事件(evaluation event)。Evaluation events包括PLI callbacks,这些callbacks是执行模型中的节点,PLI应用程序可以从仿真内核调用。所以,这些events会在不同的regions中发生。
3. Region的定义
为了支持清晰和可预测的交互,将单个time slot划分为多个region,events就被以确定的执行顺序安排到这些regions中,这就允许DUT代码和验证代码之间可预测的交互。在特定时间的所有scheduled events定义了1个time slot。在移动到下一个time slot之前,仿真按照时间顺序进行并删除掉当前仿真时间slot中的所有events,从而使得仿真前进。这个过程保证了仿真器不会在时间上倒退。一个time slot可以被划分为一组有序的regions,有:Preponed,Pre-Active,Active,Inactive,Pre-NBA,NBA,Post-NBA,Pre-Observed,Observed,Post-Observed,Reactive,Re-Inactive,Pre-Re-NBA,Re-NBA,Post-Re-NBA,Pre-Postponed,Postponed。如图1。
图1 time slot执行流程图
其中Active, Inactive, Pre-NBA, NBA和Post-NBA regions中scheduled events称为active region set events。Reactive, Re-Inactive, Pre- Re-NBA, Re-NBA和Post-Re-NBA regions中scheduled events称为reactive region set events。
Active, Inactive, Pre-NBA, NBA, Post-NBA, Pre-Observed, Observed, Post- Observed, Reactive, Re-Inactive, Pre-Re-NBA, Re-NBA, Post-Re-NBA和Pre-Postponed regions被称为iterative regions。
除了active region set和reactive region set,每个time slot的event regions可以分为simulation regions和PLI regions。图1中,圆角长方形的属于simulation regions。椭圆形的属于PLI regions。
4. Events调度参考算法
当仿真开始时,先初始化所有nets和variables的初始值,并在0 time slot上开始调度初始化events。
当发现有非空的time slot时,也就是time slot里有scheduled event。它会去执行第一个非空的time slot,就开始按照图1的流程图顺序执行各个region。当进入1个region内时,找到当前region内的scheduled event,判断event类型,如果是update event类型,更新这个event对象,且为对该event对象敏感的任何process安排evaluation event;如果是evaluation event类型,评估与这event相关的process,并可能安排进一步执行的events。
Time slot里的这些region中,Prepone、Pre-Active和Postponed只会执行一次。其它的region,具体要看event的情况,可能会执行多次。不过总体遵循这个流程:1. 顺序处理Prepone和Pre-Active region。2. 处理从Active到Post-Observed的region,会从里面找到第一个有非空event的region处理,直至全部event处理完且删掉。需要注意的是,如果在NBA region的触发了一个需要在Active region处理的event,那么会从NBA跳回Active region去处理,然后按顺序继续寻找第一个有非空event的region。3. 当步骤2的regions全部处理好之后,会开始处理从Reactive到Post_Re-NBA region,也是类似的,会从里面找到第一个有非空event的region处理,直至全部处理完毕。4. 当步骤3的region也全部处理完之后,会再重新判断下从Active到Post Re-NBA region是否还有未处理的,如果有就又要从第一个非空event的region处理,如果没有就执行Pre-Postponed region。5. 当步骤2-4里的都没有非空event的region后,处理Postponed region。6. 步骤5处理完之后,就进入到下一个time slot了。
5. Regions调度的events类别
Time slot的simulation regions包含了Preponed, Active, Inactive, NBA, Observed, Reactive, Re-Inactive, Re-NBA和Postponed regions。再根据active region set和reactive region set的划分,我们可以将一个time slot的simulation regions分为五个主要region:Preponed、Active、Observed、Reactive和Postponed。Active和Reactive可以进一步细分为小的regions。如图2所示。
图2 Simulation regions
这五大regions里调度的events有:
Prepone:在一个time slot内,Prepone region只会执行一次,当仿真时间进入当前time slot时,它是第一个被执行的region。验证环境采样DUT的信号就发生在这个region。我们平时在采样DUT信号时,会指定#1step采样延迟,#1step采样延迟提供了在进入当前time slot之前立即采样信号的能力。#1step采样相当于在当前time slot的Prepone中采样信号。所以在Preponed region的采样相当于前一个time slot Postponed region的采样。Preponed region PLI events也在这里调度。
Active:Active包含了几个小的regions:active,inactive和NBA(nonblocking assignment update) regions。
- Active region进行当前active region set events的评估求值,并且这些events会被任意处理。RTL代码和行为代码(behavioral code)被安排在active region。所有blocking assignments语句在Active region执行。对于nonblocking assignments,RHS的评估求值发生在Active region,而赋值发生在NBA region。如果有任何#0延迟的assignment,那么这些assignment发生在Inactive region。(注意:#0延迟的RHS是在inactive region是算的)
- Inactive region进行处理完所有active events后要评估的events。显式的#0延迟控制要求将这个event安排到当前time slot的inactive region进行,以便在下一个inactive到active迭代中恢复process。
- NBA region进行处理完所有inactive events后要评估的events。Nonblocking assignment会在当前或以后仿真时间的NBA region中创建events。
Observed:Observed用于触发property expressions(用于concurrent assertions)时对其求值。在property求值后,pass/fail的信息将在当前time slot的Reactive region报告出来。
Reactive:Reactive包含了Re-active,Re-inactive和Re-NBA regions。
- Re-active进行当前reactive region set的评估求值,并且可以以任何顺序进行处理。Program blocks的blocking assignments、#0 blocking assignments的RHS求值和nonblocking assignment的RHS求值发生在re-active region。另外,concurrent assertions的action blocks的代码也是在re-active region调度的。Re-active region和active region其实是对偶关系的。只不过active处理design,re-active处理program。
- Re-inactive进行处理完所有re-active events后要评估的events。Program里显示的#0延迟控制要求将这个event安排到当前time slot的re-inactive region进行,以便在下一个inactive到active迭代中恢复process。同样的,它也是inactive region的对偶关系。
- Re-NBA进行处理完所有re-inactive events后要评估的events。Program里nonblocking assignment会在当前或以后仿真时间的re-NBA region中创建events。
Postponed:postponed是当前time slot的最后1个region。$monitor, $strobe和其它相似的events会安排在这个region执行 (注意$display event是在active region和reactive region(如果在program里调用)执行的)。一旦到达postponed region,就不允许在当前time slot中发生新的值更改。在此region内,向任何net或variable进行写入值或在当前region调度任何先前region的event都是非法的。Postponed region PLI events也在这里调度。
在一个time slot里,除了上述介绍的simulation regions,还有PLI regions,在PLI regions里会去调度PLI callback。PLI regions有Preponed, Pre-Active, Pre-NBA, Post-NBA, Pre-Observed, Post-Observed, Pre-Re-NBA, Post-Re-NBA 和Pre-Postponed regions。它是图1中的椭圆型部分。本文重点讲述simulation regions,这里就不介绍PLI regions了。
6. SystemVerilog里的确定和不确定调度顺序
以下场景必须有确定的调度顺序:
- begin-end块中的语句应该按照它们在该begin-end块中出现的顺序执行。可以暂停特定begin-end块中语句的执行,以利于模型中的其它进程;但是在任何情况下,begin-end块中的语句都不得以它们在源代码中出现的顺序以外的任何顺序执行。
- NBAs语句应按照语句执行的顺序执行。
举个例子:
module test;
logic a;
initial begin
a <= 0;
a <= 1;
end
endmodule
当执行initial块时,将会有两个event被添加到NBA region。前面的规则要求它们按照执行顺序进入event region,在连续的begin-end块中,这是初始顺序。该规则要求它们去NBA region也按照这个顺序执行。因此,在仿真时间0结束时,变量a将被赋值为0,然后赋值为1。
在以下场景时,执行的顺序是不确定的:
Active events可以从active或re-active event region中取出,并以任何顺序进行处理。
过程块(procedural block)中没有时间控制结构的语句不必作为一个event执行。时间控制语句是指#expression和@expression结构。在评估过程语句时的任何时候,仿真器都可以暂停执行并将部分完成的事件作为待处理事件放置在event region中。 这样做的效果是允许进程执行的交错,尽管交错执行的顺序是不确定的并且不受用户控制。