SV-随机约束1-2-3-4

        随机验证来找bug,但是随机并不是所有,模块和系统验证差别挺大的。

        随机是产生随机的数据,

        想,要随机的是什么

        测试向量,数据可以组合。

        随机测试带来的额外负担是复杂度会提高,

        绿色环保可回收的二次使用代码。

        通过系统函数std::randomize()对变量完成随机化

        $urandom()生成一个32bit的无符号随机数。$urandom_range(max,min)生成区间的数。

        SV中,硬件中,产生随机数不是完全的free,不是完全的不受任何控制。时序等。

        软件

        硬件上,约束,有时序,硬件的功能要求。需要载体,区容纳变量以及之间的约束,载体就是类。   在SV里,载体只能类。若想把随机的变量裹在一块,而且想要每次随机他们的时候添加一些约束,那么只能是类(mod做不到,if也是,package等都做不到只有类能做到)。类可以在声明变量时,把变量声明为随机的属性,用rand和randc表示(任何整型的变量都可以声明为rand)。

        句柄也可以声明。、

       例——随机数可以由系统函数$urandom()获得;可以对动态数组做随机化;随机化时可以指定变量的随机数值范围;SV不支持对实数类型做随机化,消耗大;

        

        声明句柄,例化,做随机化。三个独立的过程。

        mod里边不能用rand

        要随机化结构体struct,结构体如果想要随机里边的成员。那么如果想要随机化结构体,结构体里面的成员要声明rand。

        失去控制,失去了数和数之间的约束。

         随机句柄的嵌套,一层一层。给句柄加rand。class A里的随机句柄指向class B,class B里的随机句柄指向class C,class C里有若干个变量。然后去随机化class A的对象时,不但会随机化class A里的变量,还会随机化里边句柄指向class B对象里的句柄成员,进一步随机化class B里的随机句柄所指向的class C对象里的变量。

        

         random为每次随机化时rand,从扑克里抽一张牌,下次随机化时重新拿一踏扑克再抽;

        randomc表示random cycle的意思randc,下次初始化还是拿第一踏的扑克牌

       

        带有随机变量的简单类

class Packet;
    //random variables
    rand bit [31:0] src, dst, data[8];
    randc bit[ 7:0] kind;
    //limite the values for src
    constraint c{src > 10;
                 src < 15;}
endclass

Packet p;
initial begin
    p = new(); //Create a packet
    if(!p.randomize())
        $finish;
    transmit(p);
end

        如果上面的句柄p未调用randomize()函数,那么p.src应是夺少?

0        间于[0:(2^32-1)]        间于[11:14]        32'hFFFFFFFF

        随机约束

        约束块

         想要放约束,最好的容器就是,结构体里不能放约束。要产生随机数,伴随着固定的约束,放到类里。   ——约束块constraint。

         两个赋值

         uniquecase是case的选项不能有重合。再constraint里表示四个变量随机化初始值不同。

         箭头。箭头可以触发事件。

          foreach轮询,循环,在constraint也可用,在其中选一个。

        硬约束,软约束。没有soft就是硬约束;当俩约束有冲突时,随机化失败。

        软约束满足不满足都行,硬约束必须满足。        一旦有冲突,follow硬约束。

class SimpleSum;
    rand bit [7:0] x, y
    bit [7:0] z;
    constraint c {z == x + y;}
endclass


//打印出来xyz结果都为0
/*如果把xyz都放到randomize函数里,虽然z没有rand属性,但是z指定了randomize。
所以结果应该是xyz都randomize;如果是randomize(z)就只有z被指定randmize。*/
module tb8;
    class simplesum;
        rand bit[7:0] x, y;
        bit[8:0] z;
        constraint cstr {
            z == x + y;
        }
    endclass
    initial begin
        simplesum ss = new();
        repeat(10) begin
            if(ss.randomize()) $display("x=%d, y=%d, z=%d", ss.x, ss.y, ss.z);
            else $error("randomize failure!");
        end
    end
endmodule

        z没有参与到rand里,不会随机化。所以z的值是0,且在constraint限制中,所以xy(无符号值)只能是0。  x = y = z = 0

        就近,就句柄近,就这个的近。       

module tb9;
    class packet1;
        rand bit[7:0] x;
        constraint cstr {soft x == 5;}
    endclass

//1.就近原则,x == x此时跳到class packet1里,x = 5。
//2.如果用{x == local::x;};时,x = 30
//3.如果想让其等于packet2里的x = 10。应{x == local::this.x;};
    class packet2;
        bit[7:0] x = 10;
        function int get_rand_x(input bit[7:0] x = 20); //默认参数
            packet1 pkt = new();
            pkt.randomize with {x == x;};
            return pkt.x;
       endfunction
    endclass
    initial begin
        packet2 pkt = new();
        $display("pkt.x = %0d ", pkt.get_rand_x(30)); //传的参数值
    end  
endmodule

        上述代码,的例子。

         local在constrint,local表示所处当前文本/域要索引x。见上述代码,local(默认参数和真正传进来的参数,不传参数就成20了)和local.this(local到class这里了,x=20,当前所在域上下文就是class packet2了,加个this即可=10。)。

 

         显然BCD

        控制——随机控制,约束。        随机和约束的部分可分开。随机可控制变量,在randomize过程中是否参与到随机化。

        rand_mode可以使能/禁止随机变量,前提是变量要拿rand声明。

        可用rand_mode来声明哪些参与否随机化。

class Packet;
    rand integer source_value, dest_value;
    ... other declarations
endclass

int ret;
Packet packet_a = new;
//Turn off all var in object
packet_a.rand_mode(0);  //对于整个类,packet_a这个句柄,packet里的变量都不参与randmize。就是让整个声明为rand变量的不参与到随机化里。(randmize前,关掉所有变量的随机化)

//...other code
//Enable source_value
packet_a.source_value.rand_mode(1);  //随机化之前,打开里面单独的变量
ret = packet_a.dest_value.rand_mode();


//等同于
packet_a.randmize(source_value)

        上述为随机化的控制。

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

        约束的控制可通过constraint_mode打开。即把整个类的所有约束块通过constraint_mode打开/关闭。指定类的某个约束块,调用其constraint_mode,打开/关闭约束块。   所以在每次randmize之前要使能一个,关闭一个,randmize才能有效,才能找到一个可解的值。

class Packet;
    rand integer source_value;
    constraint filter1 { source_value > 2 * m; }
endclass

//传进来一个句柄,如果constraint_mode是打开的,就关掉。反之则反。
function integer toggle_rand( Packet p );  //toggle翻转
    if( p.filter1.constraint_mode() )
        p.filter1.constraint_mode(0);
    else
        p.filter1.constraint_mode(1);

    toggle_rand = p.randomize();  //然后再做一个randomize
endfunction

        除了之前看到的,randomize指定变量以外,若想使能/失能某些变量的随机属性,或使能/失能类里边的约束块,都可通过rand_mode或constraint_mode。

        内嵌变量控制。

         例题——a.randomize(v, w)可能产生的随机数...

class CA;
    rand byte x, y;
    byte v, w;
    constraint c1 { x < v && y > w; };
endclass
CA a = new;
a.randomize(); //random var:x, y   ///v = 0,w = 0所以x<0,y<0
a.randomize( x ); //random var:x   ///y=8'h49,v=0,w=0所以y>w,x=8'hda<0
a.randomize( v, w );//random var:v, w   ///x=8'hda,y=8'h49,x<v=8'h74 && y>w=8'hd3
a.randomize( w, x );//random var:w, x   

        不管randomize怎样,constraint必须满足。   首先randomize()了xy,那么默认vw为0,且为满足constraint,所以x < 0,y > 0;再randomize( x ),那y v=0 w=0不变,且第一次randomize仍有效;第三次就randomize( v, w ),xy不变。

        注释值由仿真生成,打断点得出值。如下图:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值