zoukankan      html  css  js  c++  java
  • SV -- Randomization 随机化

    SV -- Randomization 随机化

    @(SV)

    0. 基础

    下面几种类型可以随机化:

    • 单个变量或整形数
    • 数组
    • 数组长度
    • 对象句柄

    语法:

    • rand bit [3:0] addr;生成0-15的随机数
    • randc bit [3:0] addr; 生成0-15的随机数,完全遍历完16个数之后才会开始开始下一轮,每一轮随机的数不重样
    • object.randomize();对象内变量随机化命令

    rand_mode:
    <object_hanlde>.<variable_name>.rand_mode(enable); 打开或关闭某个变量的随机化,或者

    <object_hanlde>.rand_mode(enable);打开或关闭某个类内的所有变量的随机化。

    class packet;
      rand byte addr;
      rand byte data;  
    endclass
     
    module rand_methods;
      initial begin
        packet pkt;
        pkt = new();
         
        //disable rand_mode of addr variable of pkt
        pkt.addr.rand_mode(0);
         
        //calling randomize method
        pkt.randomize();
         
        $display("	addr = %0d 	 data = %0d",pkt.addr,pkt.data);
         
        $display("	addr.rand_mode() = %0d 	 data.rand_mode() = %0d",pkt.addr.rand_mode(),pkt.data.rand_mode());
      end
    endmodule
    

    输出:

    addr = 0 data = 110
    addr.rand_mode() = 0 data.rand_mode() = 1
    

    1. 随机化方法

    • randomize()
    • pre_randomize()
      • 可以为类设置随机化的先决条件,例如rand_mode()
    • post_randomize()
      • 用来在随机化后进行检查

    例如下面的例子,如果在wr_rd为1的时候,address需要保持不变,定义一个pre_randomize方法来控制变量是否随机化。

    //class
    class packet;
      rand  bit [7:0] addr;
      randc bit       wr_rd;
            bit       tmp_wr_rd;    
     
      //pre randomization function - disabling randomization of addr,
      //if the prevoius operation is write.
      function void pre_randomize();
        if(tmp_wr_rd==1) addr.rand_mode(0);
        else                 addr.rand_mode(1);
      endfunction
     
      //post randomization function - store the wr_rd value to tmp_wr_rd
      //and display randomized values of addr and wr_rd
      function void post_randomize();
        tmp_wr_rd = wr_rd;
        $display("POST_RANDOMIZATION:: Addr = %0h,wr_rd = %0h",addr,wr_rd);
      endfunction
    endclass
     
    module rand_methods;
      initial begin
        packet pkt;
        pkt = new();
     
        repeat(4) pkt.randomize();
      end
    endmodule
    

    输出:

    POST_RANDOMIZATION:: Addr = 6e,wr_rd = 1
    POST_RANDOMIZATION:: Addr = 6e,wr_rd = 0
    POST_RANDOMIZATION:: Addr = 88,wr_rd = 1
    POST_RANDOMIZATION:: Addr = 88,wr_rd = 0
    

    2. Constraint

    为随机变量设置约束:
    第一种,在内部设置:

    class packet;
      rand  bit [3:0] addr;
     
      constraint addr_range { addr > 5; }
    endclass
    

    第二种,在外部设置:

    class packet;
     
      rand  bit [3:0] addr;
      //constraint block declaration
      constraint addr_range;
    endclass
     
    //constraint implementation outside class body
    constraint packet::addr_range { addr > 5; }
    

    同样,constraint也会被子类继承。

    3. inside

    让随机值约束在inside指定的范围内:
    constraint addr_range { addr inside {1,3,[5:10],12,[13:15]}; }

    constraint addr_range { addr !(inside {[5:10]}); }
    也可以将上下界指定为随机值(上下界都可以取到):

    class packet;
      rand bit [3:0] addr;
      rand bit [3:0] start_addr;
      rand bit [3:0] end_addr;
       
      constraint addr_1_range { addr inside {[start_addr:end_addr]}; }
    endclass
    

    4. dist

    可以使得随机化的数据

    constraint addr_1_range {   addr_1 dist { 2 := 5, [10:12] := 8 }; }
    

    上面的权重是这样的:
    addr == 2 , weight 5
    addr == 10, weight 8
    addr == 11, weight 8
    addr == 12, weight 8

      constraint addr_2_range {   addr_2 dist { 2 :/ 5, [10:12] :/ 8 }; }
    

    上面的权重是这样的:
    addr == 2 , weight 5
    addr == 10, weight 8/3
    addr == 11, weight 8/3
    addr == 12, weight 8/3

    5. 条件约束

    class packet;
      rand bit [3:0] addr;
           string    addr_range;
     
      constraint address_range { if(addr_range == "small")
                                    addr < 8;
                                 else
                                    addr > 8;
                               }
    endclass
    

    6. foreach 约束

    class packet;
      rand byte addr [];
      rand byte data [];
     
      constraint avalues { foreach( addr[i] ) addr[i] inside {4,8,12,16}; }
      constraint dvalues { foreach( data[j] ) data[j] > 4 * j; }
      constraint asize   { addr.size < 4; }
      constraint dsize   { data.size == addr.size; }
    endclass
    

    7. disable constraint

    跟randomize_mode一样,constraint也可以设置mode控制是否添加约束:
    pkt.addr_range.constraint_mode(0); 0表示关闭约束

    7. static constraint

    静态约束跟普通约束不同的是,静态约束的使能和关闭对所有实例都生效:

    class packet;
      rand  bit [7:0] addr;
       
      static constraint addr_range { addr == 5; }
    endclass
    

    如果下面实例化了两个packet:a1和a2,如果对a1的addr变量设置constraint_mode(0),则a2的addr的约束也会关闭。

    8. inline constraint

    inline的约束允许使用with关键字在类外对变量增加新的约束:

    class packet;
      rand bit [3:0] addr;
       
      constraint addr_range {addr inside {[6:12]};};
    endclass
     
    module inline_constr;
      initial begin
        packet pkt;
        pkt = new();
        repeat(2) begin
          pkt.randomize() with { addr == 8;};
          $display("	addr = %0d",pkt.addr);
        end
      end
    endmodule
    

    上面pkt.randomize() with { addr == 8;};将给变量添加新的约束,使得输出都为8,但是通过with添加的新约束必须包含在类中定义的范围内,否则会报错。

    9. soft constraint

    软约束是为了解决inline方式的弊端。比如有这样的场景,我们已经测试了很多正常约束的case,可能会使用with的方式来生成约束的子集,但我们永远无法通过with来生成约束的补集,而这可能在测试异常情况时需要用到。一个方法是修改constraint,但无疑会有很大麻烦。
    这时只需要在constraint中为变量增加soft关键字即可:

    class packet;
      rand bit [3:0] addr;
      constraint addr_range { soft addr > 6; }
    endclass
     
    module soft_constr;
      initial begin
        packet pkt;
        pkt = new();
     
        repeat(2) begin
          pkt.randomize() with { addr < 6;};
          $display("	addr = %0d",pkt.addr);
        end
      end
    endmodule
    

    10. unique

    使用unique关键词加在一组随机变量或者随机数组前,可以使得这些变量在约束范围内各不相同:

    rand bit [31:0] array[10];
       
      constraint array_c {unique {array}; foreach(array[i]) array[i] < 10;}
    

    11. 约束的双向性质

    上面的例子一般都只涉及单个变量的约束,而实际上sv中约束的变量是并行地设置的,因此约束中如果涉及多个约束变量的约束,则这一约束是双向的。
    例如:

    constraint c_name { if(a == 0) b == 1;
                        else       b == 0; }
    

    上面的例子b的值依赖a,而实际上a的值也会依赖b,如果将b通过inine的方式约束为1,则a也被约束为0。

    class packet;
      rand bit a;
      rand bit b;
     
      constraint a_value { a == 1; }
      constraint b_value { if(a == 0) b == 1;
                           else       b == 0; }
    endclass
     
    module bidirectional_const;
      initial begin
        packet pkt;
        pkt = new();
        pkt.randomize() with { b == 1; };
        $display("Value of a = %0d 	b = %0d",pkt.a,pkt.b);
      end
    endmodule
    

    上面的例子试图用inline的方式约束b,但b的约束会反作用到a,使得a约束为0,但a已经约束为只能为1,所以程序报错。

    12. Solve before

    solve before可以强制约束中先进行哪个变量的约束。

    在上面提到的约束双向性中,多个变量之间有依赖关系时约束是双向的,这可能会导致一些问题,比如下面的例子:

    class packet;
      rand bit       a;
      rand bit [3:0] b;
     
      constraint a_b { (a == 1) -> b == 0; }
    endclass
     
    module inline_constr;
      initial begin
        packet pkt;
        pkt = new();
        repeat(10) begin
          pkt.randomize();
          $display("	Value of a = %0d, b = %0d",pkt.a,pkt.b);
        end
      end
    endmodule
    

    b可以取0-15中的值,而只要b不为0,a都会被约束为0,所以这个例子产生的结果是这样的:

    Value of a = 0, b = 6
    Value of a = 0, b = 3
    Value of a = 1, b = 0
    Value of a = 0, b = 15
    Value of a = 0, b = 7
    Value of a = 0, b = 2
    Value of a = 0, b = 15
    Value of a = 0, b = 4
    Value of a = 0, b = 7
    Value of a = 0, b = 11
    

    a=1的情况非常少。如果我们希望a的产生不依赖b,可以使用solve before:

    class packet;
      rand bit       a;
      rand bit [3:0] b;
     
      constraint sab { solve a before b;}
      constraint a_b { (a == 1) -> b == 0;}
    endclass
     
    module inline_constr;
      initial begin
        packet pkt;
        pkt = new();
        repeat(10) begin
          pkt.randomize();
          $display("	Value of a = %0d, b = %0d",pkt.a,pkt.b);
        end
      end
    endmodule
    

    输出:

    Value of a = 0, b = 9
    Value of a = 0, b = 14
    Value of a = 0, b = 3
    Value of a = 0, b = 13
    Value of a = 1, b = 0
    Value of a = 1, b = 0
    Value of a = 1, b = 0
    Value of a = 0, b = 5
    Value of a = 0, b = 3
    Value of a = 0, b = 4
    

    13. 随机系统函数

    随机化的系统函数主要有两个:

    • urandom() 生成无符号随机数,括号内可以填入不同随机种子
      • urandom_range(max,min) 生成范围内的随机数,上下界可以不按顺序写,默认下届为0
    • random() 生成有符号随机数。
    module system_funcations;
      bit [31:0] addr1;
      bit [31:0] addr2;
      bit [64:0] addr3;
      bit [31:0] data;
      initial begin
        addr1 = $urandom();
        addr2 = $urandom(89);
        addr3 = {$urandom(),$urandom()};
        data  = $urandom * 6;
     
        $display("addr1=%0d, addr2=%0d, addr3=%0d, data=%0d",addr1,addr2,addr3,data);
      
        addr1 = $urandom_range(30,20);
        addr2 = $urandom_range(20); //takes max value as '0'
        addr3 = $urandom_range(20,30); //considers max value as '30' and min value as '20'
        $display("addr1=%0d, addr2=%0d, addr3=%0d",addr1,addr2,addr3);
      end
    endmodule
    

    输出:

    addr1=303379748, addr2=2153631232, addr3=423959822444962108, data=546103870
    addr1=27, addr2=6, addr3=25
    
  • 相关阅读:
    UVA 213 Message Decoding 【模拟】
    HDU 5976 Detachment 【贪心】 (2016ACM/ICPC亚洲区大连站)
    HDU 5979 Convex【计算几何】 (2016ACM/ICPC亚洲区大连站)
    HDU 5963 朋友 【博弈论】 (2016年中国大学生程序设计竞赛(合肥))
    HDU 5969 最大的位或 【贪心】 (2016年中国大学生程序设计竞赛(合肥))
    HDU 5968 异或密码 【模拟】 2016年中国大学生程序设计竞赛(合肥)
    HDU 5961 传递 【图论+拓扑】 (2016年中国大学生程序设计竞赛(合肥))
    HDU 5965 扫雷 【模拟】 (2016年中国大学生程序设计竞赛(合肥))
    HDU 5950 Recursive sequence 【递推+矩阵快速幂】 (2016ACM/ICPC亚洲区沈阳站)
    HDU 5952 Counting Cliques 【DFS+剪枝】 (2016ACM/ICPC亚洲区沈阳站)
  • 原文地址:https://www.cnblogs.com/lyc-seu/p/12797099.html
Copyright © 2011-2022 走看看