2.1数组约束
2.1.1 对数组属性约束
• 在约束随机标量的同时, 我们还可以对随机化数组进行约束。
class dyn size;
rand logic [31:0] d[];
constrain d size {d.size() inside {[1:10]}; }
endclass• 多数情况下, 数组的大小应该给定范围 , 防止生成过大体积的数组或者空数组。
• 此外还可以在约束中结合数组的其它方法sum () , product () , and () , or ()和xor () 。
2.1.2 对数组元素约束
• sv可以利用foreach对数组的每一个元素进行约束,和直接写出对固定大小数组的每一个元素的约束相比,foreach要更简洁。
• 针对动态数组,foreach更适合于对非固定大小数组中每个元素的约束。class good_sums;
rand uint len[];
constraintc len {
foreach (len[i]) len[i] inside {[1:255]};
len.sum() < 1024;
len.size() inside {[1:8]};}
endclass
随机的输出结果:
sum=1011, val= 83 249 197 187 152 95 40 8
sum=1012, val= 213 252 213 44 196 20 20 54
sum= 370, val= 118 76 176
sum= 976, val= 233 187 44 157 201 81 73
sum= 412, val= 172 167 73
2.1.3数组产生唯一元素值
如果想要产生一个随机数组,他的每一个元素值都是唯一的,如果使用randc数组,那么数组中的每一个元素只会独立的随机化,并不会按照我们的本意使得数组中的每一个数是唯一的。
class UniqueSlow;
rand bit[7:0] ua[64] ;
constraint C{ foreach (ua[i]) //对数组中的每一个元素操作
foreach (ua[j])
if (i!= j) //除了元素自己
ua [i] ! = ua [j] ; //和其它元素比较
}
endclass
也可以利用randc变量来辅助生成唯一元素值的数组。
class randc8;
randc bit [7:0] val;
endclass
class LittleUniqueArray;
bit[7:0] ua[64]; // Array of unique values
function void pre randomize();
randc8 rc8;
rc8 =new();
foreach (ua[i]) begin
assert(rc8.randomize());
ua[i] = rc8.val;
end
endfunction
endclass
class packet;
rand bit[3:0] da[];
constraint da {
da.size() inside {[3:5]};
foreach(da[i]) da[i] <= da[i+l];
}
endclass
packet p;
initial begin
p = new();
p. randomize() with {da.size() inside {3,5};};
end
2.1.4随机化句柄数组
• 随机句柄数组的功能是在调用其所在类的随机函数时, 随机函数会随机化数组中的每—个句柄所指向的对象。 因此随机句柄数组的声明—定要添加rand来表示其随机化的属性, 同时在调用随 机函数前要保证句柄数组中的每一个句柄元素都是非悬空的,这需要在随机化之前为每—个元素句柄构建对象。
• 如果要产生多个随机对象, 那么你可能需要建立随机句柄数组。 和整数数组不同 , 你需要在随机化前分配所有的元素, 因为随机求解器不会创建对象。 使用动态数组可以按照需要分配最大数量的元素, 然后再使用约束减小数组的大小。 在随机化时, 动态句柄数组的大小可以保持不变或减小, 但不能增加。
parameter MAX_SIZE = 10;
class RandStuff;
bit[1:0] value = 1;
endclass
class Rand.Array;
rand Randstuff array[];
constraint c {
array. size() inside
{[l:MAX_SIZE]};
function new(); //分配最大容量
array = new[MAX_SIZE];
foreach (array[i])
array[i] = new();
endfunction;
endclass
RandArray ra;
initial begin//构造数组和所有对象
ra = new(); //随机化数组,但可能会减小数组
assert(ra.randomize()) ;
foreach (ra.array[i])
$display(ra.array[i].value);
end
2.2随机控制
2.2.1随机序列
产生随机序列的另一个方法是使用SV的randsequence结构。这对于随机安排组织原子(atomic)测试序列很有帮助。
initial begin
for (int i=O; i<l5; i++) begin
randsequence (stream)
stream : cfg_read := 1 |
io read := 2 |
mem read := 5;
cfg_read : { cfg_read_task; } |
{ cfg_read_task; } cfg_read;
mem read : { mem _read_ task; } |
{ mem_read_task; } mem_read;
io read : { io_read_task; } |
{ io read task; } io read;
endsequence
end
end
我们可以使用randcase来建立随机决策树, 但它带来的问题是没有变量可供追踪调试。
initial begin
int len;
randcase
1: len = $urandorn_range(0, 2); // 10%: 0, 1, or 2
8: len = $urandorn_range(3, 5); // 80%: 3, 4, or 5
1: len = $urandorn_range(6, 7); // 10%: 6 or 7
endcase
$display("len=%0d", len);
end
总结:
• randsequence和randcase是针对轻量级的随机控制的应用。 而我们可以通过定义随机类取代上述随机控制的功能,并且由于类的继承性使得在后期维护代码时更加方便。
• randsequence的相关功能我们在协调激励组件和测试用例时, 可能会用到。
• randcase则对应着随机约束中的dist权重约束+if-else条件约束的组合。