• SystemVerilog学习-08-随机约束和线程控制


    随机约束

    简介

    随着设计变得越来越大,要产生一个完整的激励来测试设计的功能也变得越来越困难。
    定向激励的测试方法早已经无法满足检查功能完整性的要求。SoC的集成度提高带来的模块之间交互的复杂度也是指数攀升,这就使得verifier无法预测接下来用户使用过程中会发生什么样的状况。

    随机-约束,两个词组合在一起就构成了目前动态仿真验证的主流方法。随机约束测试(CRT,Constrained-Random Test)即能够产生你感兴趣的、你想不到的的测试向量,通过回归测试、替换随机种子的方式来提高单位测试用例的覆盖率收集效率。

    产生随机数

    通过系统函数**std: :randomize()**对一些变量即可完成随机化,或者称之为产生随机数并赋予这些变量。

    我们还可以通过其它一些与随机数生成有关的系统函数来产生。

    • $urandom() :可以生成一个32位的无符号随机数。

    • $urandom_range(maxval, minval=O):可以生成间与maxval与minval之间的数。

    约束

    比起任意地生成一些随机数,在面向DUT的随机激励发生过程中,为了符合协议、满足测试需求,我们还需要添加一些约束,限制随机数在符合设计需求的要求下进行随机。

    类的成员变量均可声明为"随机"属性,用rand或者randc来表示。

    修饰符rand和randc

    对于rand修饰符,表示在可生成的范围内,每个值的可能性是相同的。

    对于randc修饰符,它的值将会随机并且遍历其可取值范围。

    randc bit [1:0] y ;
    
    • 1

    image-20220630165911469

    随机变量

    任何类中的整型(bit/byte/int)变量都可以声明为rand/randc。

    定长数组、动态数组、关联数组和队列都可以声明为rand/randc,可以对动态数组和队列的长度加以约束。

    rand bit [7:0] len;
    rand integer data[];
    constraint db{ data.size == len;}
    
    • 1
    • 2
    • 3

    指向对象的句柄成员,也可以声明为rand,但是不能被声明为randc,随机时该句柄指向对象中的随机变量也会—并被随机。

    非组合型结构体可以声明为rand,非组合型的成员可以声明为rand/randc。

    约束块

    有用的激励不仅仅是随机值,变量之间也有着相互关系。没有约束的随机变量会包含许多无效的和非法的值,这会使得有效激励的产生变得低效。需要用包含一个或多个约束表达式的约束块定义这些相互关系。

    成员集合

    约束块支持整形通过set操作符来设置它们的可取值范围。

    rand integer x,y, z;
    constraint c1 {x inside {3,5,[9:15],[24:32],[y:2*y],z};}
    
    rand integer a, b, c ;
    constraint c2 { a inside {b, c};}
    
    integer fives[4]= '{ 5,10,15,20 };
    rand integer v;
    constraint c3 { v inside { fives };}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    权重分布

    除了成员集合设置,约束块也支持设置可取值的同时也为其设置随机时的权重。
    对于:=操作符,表示每一个值的权重是相同的。

    x在100 ,101,102,200和300的权重是1 - 1 - 1 - 2 - 5。

    x dist {[100:102]:= 1,200 := 2,300 :=5}
    
    • 1

    对于:/操作符,表示权重会平均分配到每一个值。

    x在100,101,102 ,200和300的权重是1/3 -1/3 - 1/3 - 2 - 5。

    x dist {[100:102]:/ 1,200 := 2,300 :=5}
    
    • 1

    唯一标识

    unique可以用来约束一组变量,使得其在随机后变量之间不会有相同的数值。
    a[2],a[3],b和excluded在随机化之后将包含不相同的数值。

    rand byte a [5];
    rand byte b;
    rand byte excluded;
    constraint u { unique {b, a [2: 3], excluded} ; }
    constraint exclusion { excluded == 5; }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    条件约束

    可以使用if-else或者->操作符来表示条件约束

    mode == little -> len < 10;
    mode == big -> len > 100 ;
    
    bit [3:0]a, b;
    constraint c {(a == 0) -> (b == 1); }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    迭代约束

    foreach可以用来迭代约束数组中的元素,这些数组可以是定长数组、动态数组、关联数组或者队列。

    class C;
    	rand byte A[]; 
    	constraint c1 { foreach (A[i]) A[i] inside
    					{2,4,8,16} ; }
    	constraint c2 { foreach (A[j]) A[j] > 2 * j; )
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    也可以使用数组的缩减方法做迭代约束。

    class c; 
    	rand bit [7:0]A[];
    	constraint c1 { A.size() == 5; }
    	constraint c2 { A.sum()< 1000; }
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5

    函数调用

    有时候在一些表达式中无法简单地来表述约束,例如要计算一个合并数组中的 1 :

    function int count_ones ( bit [9:0] w ) ;
    	for ( count_ones = 0 ; w != 0; w = w >>1 )
    	count_ones += w & 1'b1;
    endfunction
    
    • 1
    • 2
    • 3
    • 4

    可以在约束块中调用该函数来描述约束:

    constraint c1 { length == count_ones ( v ) ; }
    
    • 1

    软约束

    在没有soft描述时的约束,称为硬约束,而带有soft描述的则是软约束。软约束用来指定变量的默认值和权重。如果用户在使用时,指定了外部约束对同一个变量做二次约束,或者用户定义了子类,也对同一个变量做二次约束时,那么硬约束可以"覆盖”软约束,并宜不会导致随机数产生的失败。

    随机方法

    在类中声明的随机变量,需要伴随着类句柄调用方法randomize(),这是SV类的内建方法:

    virtual function int randomize () ;
    
    • 1

    如果随机化成功则会返回1,如果失败则会返回0。

    内嵌约束

    ·在调用类方法randomize()时可以伴随着with来添加额外的约束。

    class simplesum ;
    	rand bit [7:0]x,y,Z;
    	constraint c { z== x+y; }
    endclass
    task InlineConstraintDemo ( SimpleSum p) ;
    	int success;
    	success = p.randomize
    endtask
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    local域指向

    之前在使用内嵌约束随机时,对于同名的变量处在不同的域中,可能会出现指向模糊的情况。可以通过local:的域索引方式来明确随机变量的指向,即local::指向的变量会在包含randomize()方法的对象中。

    随机控制

    rand_mode可以用来使能或者禁止随机变量。当随机数被禁止时,它会同为声明为随机变量的普通变量—样,不会参与到随机化过程当中。
    从以下两个函数声明可以看到,可以就单个随机变量调用其rand_mode,或者对整个对象调用rand_mode来控制其中所有的随机变量。

    task object [ .random_variable] :: rand _mode ( bit on_off ) ;
    function int object.randon_variable ::rand_mode ( ) ;
    
    • 1
    • 2

    约束控制

    类似于随机控制,一些约束块或者某个类的约束块集合都可以单个控制或者集体控制。

    task object [.constraint_identifier] : :constraint_mode(bit on_off );
    function int object.constraint_identifier::constraint_mode() ;
    
    • 1
    • 2

    可以通过约束控制函数来使能或者关闭某些约束块。

    内嵌变量控制

    在使用类的随机化函数randomize()时,如果伴有参数,那么只会随机化这些变量,而其余变量无论是否之前被声明为rand/randc,都将不会参与到随机化当中。

    线程控制

    并行线程

    .Verilog中与顺序线程begin…end相对的是并行线程fork…join。SV引入了两种新新的创建线程的方法,fork…join_none和fork…join_any.

    image-20220630165942796

    • fork…join需要所有并行的线程都结束以后才会继续执行。

    • fork…join_any则会等到任何一个线程结束以后就继续执行。

    • fork…join_none则不会等待其子线程而继续执行。

    需要注意的是,fork…join_any和fork…join_none继续)狞信,其—些未完成的子程序仍将在后合运行。如果要等待这些子程序全部完成,或者停止这些子程序,可以使用wait fork或者disable fork。

    时序控制

    SV可以通过延迟控制或者事件等待来对过程块完成时序控制。延迟控制即通过#来完成。

    #10 rega = regb;
    
    • 1

    事件(event)控制即通过@来完成。

    @r rega = regb;
    @(posedge clock) rega = regb;
    
    • 1
    • 2

    wait语句也可以与事件或者表达式结合来完成。

    real AOR[];
    initial wait(AOR.size( ) > o) ....;
    
    • 1
    • 2

    reference

    1. 西电路科验证PPT
  • 相关阅读:
    关于YOLOv8不显示GFlops的问题解决
    循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(1)
    vue watch 侦听器 监视器
    Python 笔记02 (网络交互 TCP/UDP)
    【2023年11月第四版教材】第17章《干系人管理》(合集篇)
    【C++STL基础入门】list改、查操作
    图的存储之邻接矩阵
    计算机毕业设计 智慧养老中心管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解
    【节能学院】推进农业水价综合改革的意见解读
    软件之间沟通的大喇叭:Android四大组件之广播机制
  • 原文地址:https://blog.csdn.net/weixin_41445387/article/details/125544220