1. constraints的一些重要属性
- constraints可以是任何包括整型variables或整型constant的expression,如:bit, reg, logic, integer, enum, packed, struct.
- 求解存在时返回正确的值,如果constraint过约束而导致误解,返回error
- constraints时双向的,所有的expression operators都认为是双向的,包含implication operator(->)
- constraints只支持2-state value。4-state values(x/z)或4-state operators(e.g., ===, !==)都不支持,且会报错。
- constraint_mode()可以用于enable或disable任何object中的named constraint block
- rand_mode()可以用于enable或disable任何的random variable。如果一个random variable被disabled了,那么它的行为就是nonrandom variable的。
- pre\_randomize()和post\_randomize()是sv内建的函数,它们分别会自动在randomize()之前和之后调用。
- Randomize()是virtual类型的,因此它只看object类型,不管object handle是什么。
2. :=和:/区别
3. Uniqueness constraints
一组variables可以用unique来进行约束,使得在该group中variables在randomization之后,没有任何两个members有相同的值。variables的类型可以是整型scalar variable、unpacked array variable的一个(leaf element)、一片(slice)或全部。
Leaf element的定义是:
例子如下:
4. implication
constraints为定义conditional(predicated) relations提供了两种结构:implication和if-else。两种定义如下:
implication使用(->)操作符来定义一个expression中蕴含着constraint。expression可以时任何的整数sv expression 。
Implication operator的布尔等式为:a->b 等价于(!a||b)。这表明如果expression(指的是a)为真,那么产生的随机数要受到该constraint的约束,否则,随机数是unconstrainted。总得来说:就是a为true,b也要受到constraint,a为false,b就任意的。
If-else约束中expression也要求为任何的整数expression。如果expression为真,那么if里的constraint_set就要满足,如果为false,那么else里的constraint_set要满足。
5. iterative constraints
Iterative constraints允许arrayed variables使用loop variables和indexing expression或者array reduction methods去约束。
foreach iterative constraints的语法:
foreach iterative constraints中也可以嵌套conditional(predicated) relations。
对于dynamic array和queue来说,array size也是可以被约束的,如果size constraint和iterative constraint同时发生,那么会先求解size constraints,然后求解iterative constraints。还有一个就是要防止iterative超出array size,用户必须自己要排除这些无效的索引。就如下面例子的k<A.size-1,这样就不会溢出的。
6. Array reduction iterative constraints
Array reduction methods可以根据upacked array的元素值产生一个integral value。如:
7. global constraints
在constraint中包含来自其它object的random variables就称为global constraints。在有多个objects参与的randomize中,选取objects、varibales和constraints的方法:
8. Variable ordering
在constraint块中,如果想改变某些求值组合的出现概率,可以用solve…before…,它不会改变solution space,因此不会导致solver fail。
9. Functions in constraints
对于一些繁杂的expression,有些人可能喜欢用function来表达。因此sv支持在constraint expression中采用function,但要遵守一些语法:
其实也就是说function里的参数会优先求解,然后算出function的值,最后再去求解constraint。
10. Constraint guards
Constraint guards是predicate expressions,它的功能是防止产生constraints,而不是作为求解器要满足的逻辑关系,这些predicate expressions在求解constraints之前就进行evaluated的,有以下几种:
— Constants
— State variables (注意function的返回值也是state variable)
— Object handle comparisons (comparisons between two handles or a handle and the constant null)
In addition to these, iterative constraints (see 18.5.8) also consider loop variables and the size of the array
being iterated as state variables.
11. soft constraints
与soft constraints相对立的是hard constraints,solver必须要满足,否则solver failure。Soft constraints可以被其它constraint(hard constraint或higher priority soft constraint) override掉的。因此,soft constraint通常用于给random variables指定default value或distributions。
Soft constraint除了可以被hard constraint覆盖掉,还可以被其它soft constraint覆盖掉,因此,soft constraint之间是有priority的。Soft priority在最后约束,priority越高,因此,验证环境中subsequent layers比preceding layers具有更高的priority。细则如下:
Randc variable是不能使用soft constraint的。
在求解soft constraint时,constraint solver应该要满足以下属性:
如果只对soft constraints求解,那么该次求解call可以永远不失败;
如果soft constraint的求解没有失败,那么求解的结果就相当于是对hard constraint求解一样。
对于soft constraint可以被discard掉,使用disable soft语法可以将比该定义disable的constraint低priority的constraint中的soft约束都失效掉。如:
12. randomization methods
每一个class内部都自带randomize()这个virtual method。它的定义如下:
randomize()是一个virtual方法,它为class object中的所有active random variable提供random value,当然random value要符合active constraints。如果random成功,那么返回1,如果random失败,那么返回0。
每一个class也自带pre_randomize()和post_randomize()方法,注意这两个方法不是virtual的。pre_randomize()是在randomize()之前调用的,post_randomize()是在randomize()之后调用的。定义如下:
如果randomize()失败,那么post_randomize()也不会被调用的。如果randomize()失败,那么random variables要保持原来的值。
13. local:: Scope resolution
在使用randomize() with constraint block的时候,可以引用class properties或调用method(randomize with)的local variables。如果这些variables没有加限制,那么工具会先搜寻object class的内部,然后才去搜去调用method(包含method)的范围。这样的话,如果object和调用method的scope有相同名字的variables,且想要用local的就比较麻烦了,因此sv提供了local::去修改搜寻顺序。当一个variable采用local::标识了,那么工具会去local scope去找,忽略object内部的variables。如下例子:
对于在randomize with中使用this, super, local的总结如下:
14. Disabling random variables with rand_mode()
rand_mode()可以用于控制是否将random variable处于active或inactive状态。当random variable是inactive时,那么它就像是没有被rand或randc修饰的变量一样。Inactive variables不会被randomize()随机,它们的值会被solver当作state variables。所有的random variables的初始态都是active的。
从以上定义可以看出有两种方式,task方式是用于设定variable的mode,参数传1为active,参数传0为inactive。如果random\_variable省略掉,那么object内部所有的variables都是一块设定的,而且random-variable可以是unpack array和structure的。function方式时用于返回random\_variable的mode,random_variable只能是singular variable。
15. Controlling constraints with constraint_mode()
constraint_mode()可以用于控制一个constraint block是否是active或inactive的。如果constraint时inactive的,那么randomize()在调用时不会考虑该constraint的了。所有constraint的初始状态时active。
从以上定义可以看出有两种方式,task方式用于设定constraint的mode,传1表示active,传0表示inactive。如果constraint_identifier省略掉,那么object内部的所有constraints都一块设定。function方式时用于返回constraint的mode。
16. In-line random variable control
当randomize()调用时没有传参数,那么它内部所有active random variables都要赋新值。
当randomize()调用时传参数了,那么这些传的参数是该object指定random variables的全集,其余random variables都当作state variables。如下:
据以上可知,randomize()传参可以改变class内部的任何property,设置没有定义为rand或randc的都可以。不过对于该机制对于randc是无效的,它不能将nonrandom variable变成randc,也不能将randc变成non-randc的。
17. In-line constraint checker
如果调用没有random variables的class的randomize方法,那么该方法就相当于是一个checker。也就是说它没有给任何variable赋值,而只是返回状态。这样就可以用于检查内部constraint blocks是否正确。in-line rand variable control机制可以用于强制将randomize()方法作为checker来用的。方式:randomize()里传null参数来只是该次调用没有random variables需要随机的。
18. Randomization of scope variables—std::randomize()
Scope randomize function(std::randomize())使得可以在当前scope内,随机任何一个data,而不需要定义或例化一个object。它的定义如下:
在std::randomize() with中,因为指定了constraint block,所以在variable\_identifier\_list中指定的variables是random variables,而其它在constraint block中出现的variables仅仅只是state variables。
19. Random number system functions and methods
系统函数$urandom()在每次调用时会返回一个32-bit的unsigned的伪随机数。定义如下:
seed是可选的,seed可以是任何整数表达式。如果seed一致,那么random number generator(RNG)会产生相同的random numbers序列。RNG是确定的,每一次程序执行时,它会从同一个random sequence周期性的取值。但我们可以通过指定$urandom的外来变化的seed来使得它变得不确定,如将每一天的时间作为seed。
系统函数$urandom_range()会返回在指定范围内的无符号整数。定义如下:
它将返回maxval到minval之间的数,如果minval省略掉,那么范围是maxval到0。如果maxval小于minval,那么会自动翻转,确保第一个参数不小于第二个参数。
srandom()可以用于手动seeding object或thread的RNG。srandom()方法使用给定种子的值初始化对象的RNG。定义如下:
还有get\_randstate()和set\_randstate()是用于获取或设置object's RNG的状态。
20. Random stability
Random stability的概念就是:首先每个threads或objects的RNG是local的,因此一个thread返回的random value序列与其它thread或objects的RNG是无关的。Random stability适用于以下情况:
在面对user code的小改动时,testbench带有这个feature就可以有更稳定的RNG行为。另外,通过手动调整threads和objects的seed产生,可以使得random values的产生更精确控制。
21. Random stability properties
Random stability包含以下属性:
- Initialization RNG. 每一个module instance、interface instance、program instance和package都有一个initialization RNG。每一个initialization RNG都有默认的seed。默认seed时实现定义的值。一个initialization RNG应该用于创建static processes和static initializers。
- Thread stability. 每一个thread都有一个独立的RNG,该RNG用于该线程中调用的所有randomization system的使用。当一个新的动态thread创立时,它的RNG的seed值时从parent thread生成的下一次random value,该方式称为hierarchical seeding。对于一个static process创建时,它的RNG的seed是从声明该process的initialization RNG(来自module instance、interface instance、program instance或者package)的下一个random value来的。program和thread的random stability可以通过只要和之前的thread创建和RNG的完成保持一样的顺序即可。当给现存test增加新的thread时,可以加在code block的末尾,因此来保持之前创建工作的随机数的稳定性。
- Object stability. 每一个class instance(object)都有一个独立的RNG,用于该class内部所有randomization methods。当一个object创建时,它的RNG的seed是来源于创建该object的thread。当一个object是被static declaration initializer创建时,因此没有active thread,所以它的RNG的seed是initialization RNG(来自module instance、interface instance、program instance或者package)的下一个random值。Object stability可以通过只要和之前的object创建和RNG的完成保持一样的的顺序即可。为了保持RNG stability,新objects、threads和random numbers的创建应该在现存objects创建之后才进行的。
- Manual seeding. 所有咩有初始化的RNGs可以手动安排seed。结合hierarchical seed,该机制可以用于在一个subsystem的root thread定义一个简单seed,然后定义到整个subsystem的运行。
一个object的seed可以在任何thread里面改变。但是一个thread的seed只能在thread内部修改的。
22. Random weighted case—randcase
randcase引进一种类似case的语句,可以用于随机选择它包含的分支。定义如下:
Randcase_item的expression必须是非0的表达式(可以为任意表达式,而不只是常数),如果等于0,那么表示该分支不会被选中,如果所有的分支的expression都等于0,那么所有的分支都不执行,但tool会报一个warning。
randcase里选择哪一个分支是根据$urandom_range()返回的随机数来决定的,因此random values和thread的执行顺序无关的。
23. Random sequence generation—randsequence
Random sequence对于随机产生结构化stimulus特别有用,比如instructions或network traffic patterns。Sequence generator在randsequence内部使用一组规则和productions。具体语法如下:
作者:谷公子
文章来源:CSDN
推荐阅读
在芯片研发工作中,你犯过哪些“愚蠢”的错误?
UVM response_handler和get_response机制
【芯知识】SoC设计的IO PAD怎么移植到FPGA原型验证
更多FPGA干货请关注IC设计技术专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。