约束冲突时:
(1)后约束覆盖前约束
(2)子类约束覆盖父类约束
(3)外部约束覆盖内部约束
(4)强约束覆盖soft约束
(5)如果两个soft 约束冲突,按上述3条处理且随机是可以成功
1.错误写法
constraint con{
delay dist {0:/10};
}
上述写法可能导致constraint很难解,不要用上述写法。
2. 对与求和的约束的写法(防止和溢出)
bd_len_q.sum with(int'(item)) == 20
3. 数组元素不重复
class A;
rand bit [31:0] arr[];
constraint arr_size { arr.size() inside {[10:15]}; }
constraint arr_uniq { unique {arr}; }
endclass
//------------------------------------------------------------------------
//solution2
class UniqueSlow;
rand bit[7:0] ua[64];
constraint c{
foreach(ua[i])
foreach(ua[j])
if(i != j)
ua[i] != ua[j];
}
endclass
//------------------------------------------------------------------------
//solution 3
class UniqueRandc;
randc bit[7:0] val;
endclass
class LittleUniqueArray;
bit[7:0] ua[64];
function void pre_randomize();
UniqueRandc urc;
urc = new();
foreach(ua[i]) begin
assert(urc.randomize());
ua[i] = urc.val;
end
endfunction
endclass
4. 二维数组的约束
class A;
rand bit [11:0] width [];
rand bit [11:0] height [];
rand bit [11:0] rows_cols [][];
constraint width_cst {
width.size() inside{[100:5]};
height.size() inside {[200:700]};}
constraint c {rows_cols.size() == width.size();
foreach(rows_cols[ii])
rows_cols[ii].size == height.size();
}
constraint each_element {foreach(rows_cols[ii,jj])
rows_cols[ii][jj] inside {[1:255]};}
endclass
5.多个数组相互关联
有三个数组,每个元素的取值范围是1-9,三个数组的和是100,三个数组中5的个数不能超过10个。
此类问题的核心解法: 分步求解。
class multi_queue_con;
rand int q1_sum;
rand int q2_sum;
rand int q3_sum;
rand int q1_size;
rand int q2_size;
rand int q3_size;
rand bit[4:0] q1[];
rand bit[4:0] q2[];
rand bit[4:0] q3[];
constraint c_sum{
q1_sum + q2_sum + q3_sum < 100;
q1.sum() with(int'(item)) == q1_sum;
q2.sum() with(int'(item)) == q2_sum;
q3.sum() with(int'(item)) == q3_sum;
q1.size() == q1_size;
q2.size() == q2_size;
q3.size() == q3_size;
}
针对“三个数组中5的个数不能超过10个”有两种方案:
1. 三个数组中在randomize时就让 item != 5,randomize后再向数组中填充或替换5;
constraint c_item{
foreach(q1[ii]){
q1[ii] inside {[1:4],[6:9]};
}
foreach(q2[ii]){
q2[ii] inside {[1:4],[6:9]};
}
foreach(q3[ii]){
q3[ii] inside {[1:4],[6:9]};
}
}
function post_randomize();
.../完成插入5或替换5,(替换策略:由于sum有约束,所以找数组中小于5的元素进行替换)
endfunction
2. 把5的权重调低点,多randomize几次,直到符合要求。
constraint c_item{
foreach(q1[ii]){
q1[ii] dist {[1:4]:=10,5:=5,[6:9]:=10};
}
foreach(q2[ii]){
q2[ii] inside {[1:4]:=10,5:=5,[6:9]:=10};
}
foreach(q3[ii]){
q3[ii] inside {[1:4]:=10,5:=5,[6:9]:=10};
}
}
//in seq
int tq[$];
`uvm_create_on(vseq)
s_seq.new_trans.randomize()with{};
while(1)begin
tq = s_seq.new_trans.find_index with(item ==5);
if(tq.size()>10)
s_seq.new_trans.randomize()with{};
else
break;
end
`uvm_send(vseq)
数独求解
class sudoku#( int M = 3 ); // M >= 1
localparam N = M * M;
local int unsigned puzzle[N][N];
rand int unsigned box [N][N];
// The value of each box must be between 1 and N.
constraint box_con {
foreach ( box[row, col] ) {
box[row][col] inside { [ 1 : N ] };
}
}
// The boxes on the same row must have unique values.
constraint row_con {
foreach ( box[row, colA] ) {
foreach ( box[ , colB] ) {
if ( colA != colB ) {
box[row][colA] != box[row][colB];
}
}
}
}
// The boxes on the same column must have unique values.
constraint column_con {
foreach ( box[rowA, col] ) {
foreach ( box[rowB, ] ) {
if ( rowA != rowB ) {
box[rowA][col] != box[rowB][col];
}
}
}
}
// The boxes in the same MxM block must have unique values.
constraint block_con {
foreach ( box[rowA, colA] ) {
foreach ( box[rowB, colB] ) {
if ( rowA / M == rowB / M &&
colA / M == colB / M &&
! ( rowA == rowB && colA == colB ) ) {
box[rowA][colA] != box[rowB][colB];
}
}
}
}
// The box must have the same value as the puzzle's if specified (!=0).
constraint puzzle_con {
foreach ( puzzle[row, col] ) {
if ( puzzle[row][col] != 0 ) {
box[row][col] == puzzle[row][col];
}
}
}
// Sudoku solver
function int solve_this( int unsigned puzzle[N][N] );
this.puzzle = puzzle;
return this.randomize();
endfunction: solve_this
// Print the solution.
function void print();
for ( int i = 0; i < N; i++ ) begin
if ( i % M == 0 ) $write( "\n" );
for ( int j = 0; j < N; j++ ) begin
if ( j % M == 0 ) $write( " " );
$write( "%3d", box[i][j] );
end
$write( "\n" );
end
endfunction: print
endclass: sudoku