1.数组的属性约束
1)在约束随机标量的同时,我们还可以对随机化数组进行约束。
class dyn_size;
rand logic [31:0] d[];
constraint d_size {d_size() inside {[1:10]};}//约束动态数组d的size在1-10.即每个数组有1-10个数
endclass
2)多数情况下,数组的大小应该给定范围,防止生成体积过大的数组或者空数组。
3)还可以在约束中结合数组的其他方法,如:求和sum(),求积product(),与and(),或or(),异或xor()。
2.约束数组中的元素
1)SV可以利用foreach对数组的每一个元素进行约束。
2)针对动态数组,foreach更适合于对非固定大小数组中每个元素的约束。
class good_sum5;
rand uint len[];
constraint c_len {
foreach (len[i]) len[i] inside {[1:255]}; //约束数组中每个元素为1-255
len.sum() < 1024;//每个数组和小于1024
len.size() inside {[1:8]};//每个数组中数量为1-8
}
endclass
3.产生唯一元素值的数组
产生一个随机数组,它的每一个元素值都是唯一的。用两个foreach实现。
class UniqueSlow;
rand bit [7:0] ua[64];
constraint c {
foreach (ua[i])
foreach (ua[j])
if (i != j)
ua[i] != ua[j]
}
endclass
现在可以用unique关键字实现元素值唯一。
例题:下面哪些可能是随机化的p.da的数组值?
class packet;
rand bit [3:0] da[];
constraint da {
da.size() inside {[3:5]};
foreach(da[i]) da[i] <= da[i + 1];
}
endclass
packet p;
initial begin
p = new();
p.randomize() with {da.size() inside {3,5};};
end
解析:一开始约束size为3-5,后来进行了独立约束size为3或5,这没看AC是对的。但是foreach(da[i]) da[i] <= da[i + 1];时没有限制i的取值,当i = 5时,i的范围时[0:4].da[4] <= da[5],而5超出了范围,所以约束有冲突,随机化失败,会报错。答案为D
解决办法:限制i的取值范围为[0 : da.size - 2]
4.随机化句柄数组
1)随机句柄数组的功能是在调用其所在类的随机函数时,随机函数会随机化数组中的每一个句柄所指向的对象。因此随机句柄数组的声明一定要添加rand来表示其随机化的属性,同时在调用随机函数前要保证句柄数组中的每一个句柄元素都是非悬空的,这需要在随机化前为每一个元素句柄构建对象。
2)如果要产生多个随机对象,那么需要建立随机句柄数组。和整数数组不同,需要在随机化前分配所有的元素,因为随机求解器不会创建对象。使用动态数组可以按照需要分配最大数量的元素,然后再使用约束减少数组的大小,在随机化时,动态句柄数组的大小可以保持不变或减小,但不能增加。
例题:根据代码,判断下面选项哪组正确?
parameter MAX_SIZE = 10;
class RandStuff;
bit [1:0] value = 1;
endclass
class RandArray;
rand RandStuff array[];
constraint c{
array.size() inside {[1: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()with {array.size == 2});
foreach (ra.array[i])
$display(ra.array[i].value);
end
解析:因为randstuff这个class里面的变量没有进行随机化,就是固定的1,所以答案时B。如果把bit [1:0] value = 1变成rand bit [1:0] value 那么value在0-3都对。