Consider the following, if two lists are not equal then there is at least one location where the values are different.
Therefore,
l1 is different than l2 if and only if there exists a 'diff_at' such that l1[diff_at]!=l2[diff_at]
Using this approach the entire DB can be generated in a single CFS:
struct db_wrapper_s {
DB : list of list of uint;
diff_at : list of list of uint;
keep DB.size() == diff_at.size();
keep for each in diff_at {
it.size() == index;
for each in it {
it < read_only(DB[index].size());
};
};
keep for each (diff_i) using index (i) in diff_at {
for each (diff_i_j) using index (j) in diff_i {
DB[i][diff_i_j] != DB[j][diff_i_j];
};
};
};
generate_new_data() is {
var genDB : db_wrapper_s;
var db_sz : uint = 10;
var l_sz : uint = 5;
gen genDB keeping {
it.DB.size() == read_only(db_sz);
for each in it.DB {
it.size() == read_only(l_sz);
};
};
print genDB.DB;
};
The problem with the above is it will proabaly suffer from long solving time if the amount of lists in DB and the list size are large.
Since Specman 14.2 the random generator supports generative list index:
keep foo()[gen_var] == ... ;
(The feature is disabled in 14.2/15.1 and need to turned on by "config gen -use_generative_list_index=TRUE").
Using this feature you can build the DB list by list:
struct new_list_wrapper_s {
new_list : list of uint;
diff_at : list of uint;
};
!DB : list of list of uint;
generate_new_data() is {
var n : uint = 5;
for i from 1 to 10 {
var new_list_wrapper : new_list_wrapper_s;
gen new_list_wrapper keeping {
it.diff_at.size() == read_only(DB.size());
it.new_list.size() == read_only(n);
for each (diff_loc) in it.diff_at {
diff_loc < read_only(n);
it.new_list[diff_loc] != read_only(DB[index])[diff_loc];
};
};
DB.add( new_list_wrapper.new_list );
};
print DB;
};