• 第六章:随机化(续1)


    6.6 pre_randomize和post_randomize函数

    我们在调用randomize()函数之前或者之后要立即执行一些操作。比如,在随机化之前可能要设置类里的一些非随机变量(上下限、权重),或者随机化之后需要计算随机数据的误差矫正位。
    SystemVerilog中可以使用void类型的pre_randomize和post_randomize函数来完成这些功能。void类型的函数并没有返回值,与任务不同,并不会消耗时间。

    6.6.1 构造浴缸型分布函数

    我们在实际的应用中,通常要用到一些非线性的随机分布,这时候我们希望能够有一种浴缸型的分布,在两端的概率大,中间的概率小。
    可以通过详细描述dist约束构造浴缸型的分布,但是需要多次调整才能获得需要的形状。
    在Verilog中,我们已经提供了很多非线性函数,例如:$dist函数,但是并没有浴缸型函数,这时我们可以通过两条指数曲线去构造我们想要的函数。
    常用的函数:

    • $random() ——平均分布,返回32比特有符号随机数;
    • $urandom() ——平均分布,返回32比特无符号随机数;
    • $urandom_range() ——在指定范围内的平均分配;
    • $dist_exponential() ——指数衰落;
    • $dist_normal() ——钟型分布;
    • $dist_poisson() ——钟型分布;
    • $dist_uniform() ——平均分布;
      浴缸型分布
      构造浴缸型分布
      值得一提的是由于变量value是由function计算得到的,而不是随机约束求解器得到的,所以并不需要rand修饰符定义。

    6.7 约束的技巧和技术

    我们怎样才能写出便于维护和修改的CRT?通常是有一些小技巧的。下面我们就这些技巧做一下介绍。

    6.7.1 使用变量的约束

    通常一些上下限还有一些权重值,可以通过设置一个变量来维护。
    权重
    可以通过改变read8_wt=0,来禁止这项命令生效。缺省情况下,read8_wt,read16_wt,read32_wt是1,1,1.

    6.7.2 用约束检查值的有效性

    调用handle.randomize()函数的同时,SystemVerilog会检查这些变量是否满足约束条件。

    6.7.3 调试函数

    在随机化的过程中,为了输出随机化的结果,我们通常会设置function void display()函数来进行可视化输出。

    6.7.4 非随机值的使用

    如果一套的随机约束已经产生了大部分你想要的激励向量,只有少数几个向量需要修改,那么你可以使用rand_mode()函数把这些变量设置成非随机变量。
    使用rand_mode禁止变量的随机化
    利用调试函数得出结果
    结果
    对length变量进行rand_mode()设置以后,约束丧失了对length的约束能力。

    6.7.5 随机化个别变量

    上一小节,我们讲了从一个大的约束里面除去对某个变量的约束,那么这一小节我们来讲,只对某一个或者某几个变量进行约束。
    在调用randomize()函数时只传递变量的一个子集,这样的话就只会随机化类里面的几个变量。只有参数列表里面的变量才会被随机化。所有的约束仍然保持有效。
    随机化类里面的一部分变量
    low是一个非随机变量,却被随机化赋于了一个随机值,并且满足约束条件。

    6.7.5 打开或关闭约束

    如果利用if-else语句声明的约束显得很复杂,可读性不是很强的情况下,可以采用打开或关闭进行约束。

    6.7.6 在测试过程中使用内嵌约束

    使用random()with{}内嵌约束语句使约束的作用范围局部化,作为对约束的补充是一种很好的做法。但是与之而来的问题是约束代码位于代码不同的位置,还难维护;其次很难在不同的测试里复用这些内嵌约束。

    6.7.7 在测试过程中使用外部约束

    我们知道函数的函数体可以在函数的外部定义,同样,约束的约束体也可以在类的外部定义。
    带有外部约束的类带有外部约束的程序

    • 外部约束可以放到另一个文件中,从而在不同的测试里可以复用外部约束。
    • 外部约束对类的所有实例都起作用,而内嵌约束仅仅影响一次randomize()调用。

    6.8 随机化常见的错误

    6.8.1 小心使用有符号变量
    • 除非必要,不要在随机约束里使用有符号的数据类型。
    • 在使用无符号的数时,一定要注意是否溢出,这个问题可以通过限制位宽来解决。

    6.9 迭代和数组约束

    以上篇幅我们都只对标量类型的变量进行约束,现在思考如何在随机化数组时进行约束?
    利用foreach约束和一些数组函数可以改变值的分布性状。
    利用foreach会影响仿真器的运行速度,特别是遇到foreach嵌套的时候,这个时候我们可以通过使用randc变量来代替foreach的嵌套。

    6.9.1 数组的大小

    size()函数可以用来约束动态数组或队列里的元素个数。
    约束动态数组的大小
    一定要设置数组的上限,否则会产生成千上万个元素。

    6.9.2 数组元素的和

    sum()函数可以用于约束数组中元素的和。在使用sum()函数的时候,你需要注意一下几点:

    • 使用无符号的数
    • 注意位宽
    • 注意溢出问题
    6.9.3 约束数组和队列的每一个元素

    foreach能够对数组里的每一个元素进行约束。
    foreach约束
    使用foreach产生递增的数组元素的值
    foreach约束只能有一个数组名,不允许使用层次化的引用。

    6.9.4 产生具有唯一元素值的数组

    **怎么才能产生一个随机数组,使它的每一个元素的值都是唯一的呢?
    方法一:使用嵌套的foreach循环让求解器比较任意两个元素,但是这样会降低仿真器的求解速度。
    foreach的嵌套
    方法二:使用包含randc变量辅助类,这样的话就可以不断随机化同一个变量。
    使用randc辅助类产生唯一的元素值
    方法三:最为常用的一种方法。将方法二中的常量参数化。
    唯一值发生器
    产生元素具有唯一值的随机数组的类

    • new函数用来产生max_value,用于RandcRange的参数输入。
    • display函数用于调试输出。
      使用类
  • 相关阅读:
    online ddl与pt-osc详解
    几个重点问题回顾
    死锁及常见死锁模型
    InnoDB中锁的算法(3)
    一个幻读模型引出的记录可见性判断
    jupyter notebook的使用
    l线程池抓取lianjia
    lagou数据爬取
    爬虫代理的设置
    linux如何安装和启动mongdb
  • 原文地址:https://www.cnblogs.com/xuqing125/p/9550580.html
Copyright © 2020-2023  润新知