Hi,
I’m trying to randomly distribute a payload array throughout a scatter gather list, defined as follows.
rand byte sgl[][][16];
rand byte unsigned payload[];
rand int unsigned payload_desc[];
constraint C_PAYLOAD_DISTRIBUTION {
payload_desc.size == sgl.size;
payload_desc.sum with (longint'(item)) == payload.size;
}
I can use the above constraint, but this only constrains payload_desc.size to have the size of the outer dimension of the array.
What I really need is to be able to determine the total size of all the dynamic dimensions in the array, like this.
function int total_size(sgl_t x);
foreach (x[i,]) begin
total_size += x[i].size;
end
return total_size;
endfunction
And then write the constraint as follows
constraint C_PAYLOAD_DISTRIBUTION {
payload_desc.size == total_size(sgl);
payload_desc.sum with (longint'(item)) == payload.size;
}
But, as I believe the function is always called before the constraint is resolved, this doesn’t work, i.e. total_size always returns 0.
Can anybody see an alternative way to achieve this?
Dale
In reply to dshanley:
Randomization method can not create a dynamic array by it self. Therefore function ‘total_size’ return zero (a default value of int total_size).
A array sql should be created by constraint; sql.size.
A solution
// Purpose:
// Conclusion:
module top;
typedef byte sgl_t[][][16];
// Class
class myclass;
rand byte sgl[][][16];
rand byte unsigned payload[];
rand int unsigned payload_desc[];
// Array creation
constraint c_sgl_size { sgl.size == 5;
payload.size == 15;
foreach(sgl[i]) {
sgl[i].size == 2;
}
}
function int total_size(sgl_t x);
foreach (x[i,]) begin
total_size += x[i].size();
end
return total_size;
endfunction
constraint C_PAYLOAD_DISTRIBUTION {
solve sgl before payload_desc;
payload_desc.size == total_size(sgl);
payload_desc.sum with (longint'(item)) == payload.size;
}
function void post_randomize();
$display("payload_desc size = %d ", payload_desc.size());
$display("sgl size = %d ", sgl.size());
foreach(sgl[i,]) begin
$display("sgl[%1d].size= %d ", i, sgl[i].size);
end
foreach(payload_desc[i]) begin
$display("payload_desc[%1d]= %d ", i, payload_desc[i]);
end
endfunction: post_randomize
endclass // myclass
initial
begin
myclass c;
c= new();
if(!c.randomize()) begin
$display("Randomize fail ");
end
else begin
$display("Randomize Pass");
end
end
endmodule // top;
In reply to prashant.kaushik:
Hi,
Thanks for your help, but it still doesn’t work for me.
The total_size function always returns 0 and the solver fails.
The “solve sgl before payload_desc;” doesn’t appear to have any effect.
If I hack the total_size function to return, say 3. Then the solver passes as expected.
module top;
typedef byte sgl_t[][][16];
// Class
class myclass;
rand byte sgl[][][16];
rand byte unsigned payload[];
rand int unsigned payload_desc[];
// Array creation
constraint c_sgl_size { sgl.size == 5;
payload.size == 15;
foreach(sgl[i,,]) {
sgl[i].size == 2;
}
}
function int total_size(sgl_t x);
foreach (x[i,]) begin
total_size += x[i].size();
end
return total_size;
//return 3;
endfunction
constraint C_PAYLOAD_DISTRIBUTION {
solve sgl before payload_desc;
payload_desc.size == total_size(sgl);
payload_desc.sum with (longint'(item)) == payload.size;
}
function void post_randomize();
$display("payload_desc size = %d ", payload_desc.size());
$display("sgl size = %d ", sgl.size());
foreach(sgl[i,]) begin
$display("sgl[%1d].size= %d ", i, sgl[i].size);
end
foreach(payload_desc[i]) begin
$display("payload_desc[%1d]= %d ", i, payload_desc[i]);
end
endfunction: post_randomize
endclass // myclass
initial
begin
myclass c;
c= new();
if(!c.randomize()) begin
$display("Randomize fail ");
end
else begin
$display("Randomize Pass");
end
end
endmodule // top;
In reply to dshanley:
My example is working in Questa 10.3d and 10.4c, without hacking ‘return value’ of function.
One of the output is:
ayload_desc size = 10
sgl size = 5
sgl[0].size= 2
sgl[1].size= 2
sgl[2].size= 2
sgl[3].size= 2
sgl[4].size= 2
payload_desc[0]= 0
payload_desc[1]= 0
payload_desc[2]= 5
payload_desc[3]= 0
payload_desc[4]= 10
payload_desc[5]= 0
payload_desc[6]= 0
payload_desc[7]= 0
payload_desc[8]= 0
payload_desc[9]= 0
Randomize Pass
It seems me that there should be a tool issue.
VC_45
5
In reply to prashant.kaushik:
try the following with the tmpArr and without using any function ‘total_size’ also…
then, it seems to be working fine…
module top;
typedef byte sgl_t[16];
// Class
class myclass;
rand byte sgl[16];
rand byte unsigned payload[];
rand int unsigned payload_desc[];
rand int tmpArr[];
// Array creation
constraint c_sgl_size { sgl.size == 5;
payload.size == 15;
**tmpArr.size == sgl.size;**
foreach(sgl[i]) {
sgl[i].size == 2;
**tmpArr[i] == sgl[i].size;**
}
}
constraint C_PAYLOAD_DISTRIBUTION {
solve sgl before payload_desc;
**payload_desc.size == tmpArr.sum with (int'(item));**
payload_desc.sum with (longint'(item)) == payload.size;
}
function void post_randomize();
$display("payload_desc size = %d ", payload_desc.size());
$display("sgl size = %d ", sgl.size());
foreach(sgl[i,]) begin
$display("sgl[%1d].size= %d ", i, sgl[i].size);
end
foreach(payload_desc[i]) begin
$display("payload_desc[%1d]= %d ", i, payload_desc[i]);
end
endfunction: post_randomize
endclass // myclass
initial
begin
myclass c;
c= new();
if(!c.randomize()) begin
$display("Randomize fail ");
end
else begin
$display("Randomize Pass");
end
end
endmodule // top;
In reply to prashant.kaushik:
I agree it looks like a tool issue, I’m using vcs_mx/K-2015.09-SP2.
If I use vinod’s suggested workaround, it works OK.
Thanks for your help
In reply to vinod cheedella:
Thanks,
Your suggestion works for me - reproduced here, as I’d spotted a typo in your c_sgl_size constraint.
module top;
typedef byte sgl_t[][][16];
// Class
class myclass;
rand byte sgl[][][16];
rand byte unsigned payload[];
rand int unsigned payload_desc[];
rand int tmpArr[];
// Array creation
constraint c_sgl_size { sgl.size == 5;
tmpArr.size == sgl.size;
payload.size == 15;
foreach(sgl[i,,]) {
sgl[i].size == 2;
tmpArr[i] == sgl[i].size;
}
}
constraint C_PAYLOAD_DISTRIBUTION {
payload_desc.size == tmpArr.sum with (int'(item));
payload_desc.sum with (longint'(item)) == payload.size;
}
function void post_randomize();
$display("payload_desc size = %d ", payload_desc.size());
$display("sgl size = %d ", sgl.size());
foreach(sgl[i,]) begin
$display("sgl[%1d].size= %d ", i, sgl[i].size);
end
foreach(payload_desc[i]) begin
$display("payload_desc[%1d]= %d ", i, payload_desc[i]);
end
endfunction: post_randomize
endclass // myclass
initial
begin
myclass c;
c= new();
if(!c.randomize()) begin
$display("Randomize fail ");
end
else begin
$display("Randomize Pass");
end
end
endmodule // top;
Here is the output,
payload_desc size = 10
sgl size = 5
sgl[0].size= 2
sgl[1].size= 2
sgl[2].size= 2
sgl[3].size= 2
sgl[4].size= 2
payload_desc[0]= 12
payload_desc[1]= 1
payload_desc[2]= 1
payload_desc[3]= 1
payload_desc[4]= 0
payload_desc[5]= 0
payload_desc[6]= 0
payload_desc[7]= 0
payload_desc[8]= 0
payload_desc[9]= 0
Randomize Pass
In reply to dshanley:
Sorry, just noticed that you actually didn’t have a typo.