I could not answer this question completely. Only solved for the size of the arrays; Your help will be appreciated:
// There are 40 cards of 4 colors RED,BLUE,GREEN,YELLOW and numbered from 0-9.
// I would like to pick set of 7 cards comprising of 2 sets.
//Set 1 has to have a minimum of 3 cards in sequence. Cards have to be of the same color.
//Set 2 has to have a minimum of 3 cards. Cards have to be of the same number but different color.
//----------------------------------------------//
class stimuli;
typedef enum bit[1:0] {RED, BLUE, GREEN, YELLOW} COLOR;
typedef struct packed {COLOR c; int unsigned num;} CARD;
rand COLOR c_set_1[];
rand COLOR c_set_2[];
rand int unsigned n_set_1[];
rand int unsigned n_set_2[];
CARD sol[7];
constraint c_sizes {(this.c_set_1.size()+this.c_set_2.size()) == 7;
this.c_set_1.size() >= 3;
this.c_set_2.size() >= 3;
this.c_set_1.size() == this.n_set_1.size();
this.c_set_2.size() == this.n_set_2.size();}
constraint co_set_1 {
foreach (this.n_set_1[i]) {
this.n_set_1[i] inside{[0:9]};
(i > 0) -> (this.n_set_1[i] == this.n_set_1[i-1]+1);
(i > 0) -> (this.c_set_1[i] == this.c_set_1[i-1]);
}
}
constraint co_set_2 {
unique {this.c_set_2};
// To prevent having a repeated card between sets, if commented the checker in the module will fail
unique {this.n_set_2[0], this.n_set_1};
foreach (this.n_set_2[i]) {
this.n_set_2[i] inside{[0:9]};
(i > 0) -> (this.n_set_2[i] == this.n_set_2[i-1]);
}
}
function void post_randomize();
// Filing the solution array
foreach(this.c_set_1[i]) begin
this.sol[i].c = this.c_set_1[i];
this.sol[i].num = this.n_set_1[i];
end
foreach(this.c_set_2[i]) begin
this.sol[i+this.c_set_1.size()].c = this.c_set_2[i];
this.sol[i+this.c_set_1.size()].num = this.n_set_2[i];
end
endfunction
endclass
//----------------------------------------------//
module test;
initial begin
stimuli s;
stimuli::CARD q[$];
s = new();
repeat(10) begin
s.randomize();
$display("%p", s.sol);
// Check if there is a repeated card
q = s.sol.unique;
if($size(q) !== $size(s.sol)) begin
$error("There is a repeated card in between sets!!!!");
$finish;
end
end
end
endmodule
// 1. array of different color is followed array of same color
// 2. array of same values is followed by array of different values
Other possibility is
// 1. array of same color and array of different color
// 2. array of different values and array of same values
which is not covered.
class cards;
typedef enum {RED,BLUE,GREEEN,YELLOW} colour_e;
rand colour_e col_1[],col_2[],col;
rand bit[3:0] val_1[],val_2[],val;
randc bit mode;
colour_e colour_array[];
bit[3:0] val_array[];
// There are set of 2 arrays one set for colours and other set for values
constraint val_size_c {
col_1.size() inside{3,4};
col_2.size() inside{3,4};
val_1.size() inside{3,4};
val_2.size() inside{3,4};
col_1.size() == val_1.size();
col_2.size() == val_2.size();
col_1.size() + col_2.size() == 7;
val_1.size() + val_2.size() == 7;
}
// col_1 array elements are of different colour
// val_1 array elements are in sequence
constraint uniq_c {
unique {col_1};
foreach(val_1[i]) {
val_1[i] inside {[0:9]};
if(i) {
val_1[i] == val_1[i-1]+1; // Incr order
}
}
}
// col_2 array elements are of same colour
// val_2 array elements are of same value
constraint same_c {
foreach(col_2[i]) {
val_2[i] inside {[0:9]};
if(i) {
col_2[i] == col_2[i-1]; // Same colour
val_2[i] == val_2[i-1]; // same value
}
}
}
function void post_randomize();
colour_array = new[col_1.size() + col_2.size()];
val_array = new[val_1.size() + val_2.size()];
$display("mode =%0d",mode);
// Based on mode concatenate the arrays,
// Mode 0 :
// 1. array of different colour and array of same colour
// 2. array of same values and array of differnt values
// Mode 0 :
// 1. array of same colour and array of different colour
// 2. array of different values and array of same values
case(mode)
0 : begin
colour_array = {col_1,col_2};
val_array = {val_2,val_1};
end
1 : begin
colour_array = {col_2,col_1};
val_array = {val_1,val_2};
end
endcase
endfunction
endclass
module test;
cards cc;
bit suc;
initial begin
cc = new();
repeat(10) begin
suc = cc.randomize();
$display("*******************************************************************");
$display("Value = %p",cc.val_array);
$display("Colour = %p",cc.colour_array);
$display("*******************************************************************");
end
end
endmodule
Other possibility is
// 1. array of same color and array of different color
// 2. array of different values and array of same values
which is not covered.
Actually nothing mentioned in the question for this, i.e. I named the two sets: set1 & set2 but it doesn’t matter which one is the first one and you can name them: setSameColor & setSameNumber or any other names.
Please notice that your answer doesn’t really follow the requirements mentioned in the question, separating the arrays and concatenate them in post_randomize actually produce some incorrect results, also doesn’t consider that we are picking cards from 40 cards pool, i.e. no cards should be picked twice.
Please give it a try (2) - EDA Playground … the above is one run and you see that the 4th item in the first and second results doesn’t belong to any set, and in the third result: GREEN-1 card is picked twice
Here is a different approach. Create a deck of cards and have the constraints solver pick a card from the deck
module test;
typedef enum {RED, BLUE, GREEN, YELLOW} color_e;
typedef struct {
color_e color;
int unsigned number;
} card_s;
class Problem;
card_s Deck[$];
rand int unsigned set1[], set2[]; // Represents an index into the Deck
function new;
color_e c_itr; // color iterator
int n_itr; // number iterator
// create full deck of 40 cards
do begin
for (n_itr=0;n_itr<10;n_itr++) // loop over 10 numbers
Deck.push_back('{c_itr,n_itr});
c_itr = c_itr.next;
end while (c_itr != c_itr.first()); // loop over 4 colors
endfunction
constraint c_sizes {
set1.size inside {[3:4]};
set2.size inside {[3:4]};
(set1.size + set2.size) == 7;
}
constraint c_picks {
foreach (set1[i]) set1[i] < Deck.size();
foreach (set2[i]) set2[i] < Deck.size();
unique {set1, set2}; // can only pick a card once
}
constraint c_set1 {
foreach (set1[i]) i > 0 -> {
Deck[set1[i]].color == Deck[set1[i-1]].color; // colors are the same
Deck[set1[i]].number == Deck[set1[i-1]].number + 1; // numbers in sequence
}}
constraint c_set2 {
foreach (set2[i]) foreach (set2[j]) i != j ->
Deck[set2[i]].color != Deck[set2[j]].color; // colors are different
foreach (set2[i]) i > 0 -> {
Deck[set2[i]].number == Deck[set2[i-1]].number; // numbers are the same
}}
endclass
Problem P = new;
initial repeat (10) begin
assert (P.randomize());
$display("set1");
foreach (P.set1[i]) $write(" %p ",P.Deck[P.set1[i]]);
$display("\nset2");
foreach (P.set2[i]) $write(" %p ",P.Deck[P.set2[i]]);
$display();
end
endmodule
Oh My bad.
Thanks M.Wafa for pointing me the mistakes. I have fixed them.
Fixed Code is
class cards;
typedef enum {RED,BLUE,GREEEN,YELLOW} colour_e;
rand colour_e col_1[],col_2[],col;
rand bit[3:0] val_1[],val_2[],val;
randc bit mode;
colour_e colour_array[];
bit[3:0] val_array[];
// There are set of 2 arrays one set for colours and other set for values
constraint val_size_c {
col_1.size() inside{3,4};
col_2.size() inside{3,4};
val_1.size() inside{3,4};
val_2.size() inside{3,4};
col_1.size() == val_2.size();
col_2.size() == val_1.size();
col_1.size() + col_2.size() == 7;
val_1.size() + val_2.size() == 7;
}
// col_1 array elements are of different colour
// val_1 array elements are in sequence
constraint uniq_c {
unique {col_1};
foreach(val_1[i]) {
val_1[i] inside {[0:9]};
if(i) {
val_1[i] == val_1[i-1]+1; // Incr order
}
}
}
// col_2 array elements are of same colour
// val_2 array elements are of same value
constraint same_c {
foreach(val_2[i]) {
val_2[i] inside {[0:9]};
if(i) {
val_2[i] == val_2[i-1]; // same value
}
}
foreach(col_2[i]) {
if(i) {
col_2[i] == col_2[i-1]; // Same colour
}
}
}
constraint uniq_bw_array_c {
unique {val_2[0],val_1}; // To have unique values no repetitions
}
function void post_randomize();
colour_array = new[col_1.size() + col_2.size()];
val_array = new[val_1.size() + val_2.size()];
$display("mode =%0d",mode);
// Based on mode concatenate the arrays,
// Mode 0 :
// 1. array of different colour and array of same colour
// 2. array of same values and array of differnt values
// Mode 0 :
// 1. array of same colour and array of different colour
// 2. array of different values and array of same values
case(mode)
0 : begin
colour_array = {col_1,col_2};
val_array = {val_2,val_1};
end
1 : begin
colour_array = {col_2,col_1};
val_array = {val_1,val_2};
end
endcase
endfunction
endclass
module test;
cards cc;
bit suc;
initial begin
cc = new();
repeat(10) begin
suc = cc.randomize();
$display("*******************************************************************");
$display("Value = %p",cc.val_array);
$display("Colour = %p",cc.colour_array);
$display("*******************************************************************");
end
end
endmodule