Reputation: 1992
class ns_data_struct;
rand bit [63:0] ns_size = 64'h0000_0000_0000_0800;
endclass : ns_data_struct
class conf;
ns_data_struct ns_data[];
function new();
ns_data = new[5];
foreach (ns_data[i])
ns_data[i] = new();
endfunction
endclass : conf
class x;
randc bit [63:0] slba;
randc bit [63:0] nlb;
bit [63:0] slba_previous [bit [31:0]][bit [63:0]];
conf cfg;
bit [31:0] nsid = 'h1;
bit [63:0] num [bit [31:0]];
constraint slba_nlb_inside_ns_c
{
slba inside {[1:cfg.ns_data[nsid-1].ns_size]};
nlb inside {[0:(cfg.ns_data[nsid-1].ns_size - slba)]};
}
constraint slba_nlb_non_overlapping_c
{
foreach(slba_previous[nsid, i])
{
if(!(i%2))
{
slba < slba_previous[nsid][i] -> (slba + nlb) < slba_previous[nsid] [i];
slba > slba_previous[nsid][i] -> slba > slba_previous[nsid][i+1]; // <-- Warning Here
slba > slba_previous[nsid][i+1] -> (slba + nlb) > slba_previous[nsid][i+1]; // <-- Warning Here
slba < slba_previous[nsid][i+1] -> slba < slba_previous[nsid][i]; // <-- Warning Here
}
}
}
function void post_randomize();
num[nsid] = (num.exists(nsid))?(num[nsid]):0;
slba_previous[nsid][num[nsid]++] = slba;
slba_previous[nsid][num[nsid]++] = (slba + nlb);
$display("\nslba_previous - %p\n", slba_previous);
endfunction
function new (input conf _cfg);
this.cfg = _cfg;
endfunction: new
endclass : x
program p1;
conf c;
x t;
initial
begin
c = new;
t = new(c);
t.nsid = 3;
for(int i=0; i<15; i++)
begin
if(!t.randomize())
$display("ERROR : Starting LBA & NLB Provider Randomization Failed");
$display("@%0t : KARAN, Starting LBA - %0h %0d", $time, t.slba, t.slba);
$display("@%0t : KARAN, Number of LBA - %0h %0d", $time, t.nlb, t.nlb);
end
end
endprogram
In this code, I am facing 2 issues in QuestaSIM.
In the constraint, I have used (i%2), still it is showing this warning:
Warning : (vsim-3829) Non-existent associative array entry. Returning default value.
How to loop through lower dimension in 2 dimensional associative array in a constraint? foreach(slba_previous[, i])
is not working.
Upvotes: 1
Views: 2512
Reputation: 1992
Warning can be resolved, by modifying class x, as below, in which associative array is splited into 2 arrays.
class x;
randc bit [63:0] slba;
randc bit [63:0] nlb;
bit [63:0] slba_previous_low [bit [31:0]][bit [63:0]];
bit [63:0] slba_previous_high [bit [31:0]][bit [63:0]];
conf cfg;
bit [31:0] nsid = 'h1;
bit [63:0] num [bit [31:0]];
constraint slba_nlb_inside_ns_c
{
slba inside {[1:cfg.ns_data[nsid-1].ns_size]};
nlb inside {[0:(cfg.ns_data[nsid-1].ns_size - slba)]};
}
constraint slba_nlb_non_overlapping_c
{
foreach(slba_previous_low[id, i])
{
if(id == nsid)
{
slba < slba_previous_low[id][i] -> (slba + nlb) < slba_previous_low[id] [i];
slba > slba_previous_low[id][i] -> slba > slba_previous_high[id][i];
slba > slba_previous_high[id][i] -> (slba + nlb) > slba_previous_high[id][i];
slba < slba_previous_high[id][i] -> slba < slba_previous_low[id][i];
}
}
}
function void post_randomize();
num[nsid] = (num.exists(nsid))?(num[nsid]):0;
slba_previous_low[nsid][num[nsid]] = slba;
slba_previous_high[nsid][num[nsid]] = (slba + nlb);
num[nsid]++;
$display("\nslba_previous_low - %p\n", slba_previous_low);
$display("\nslba_previous_high - %p\n", slba_previous_high);
endfunction
function new (input conf _cfg);
this.cfg = _cfg;
endfunction: new
endclass : x
Upvotes: 0
Reputation: 19112
When using a foreach
on an double associative array, you need to include all the significant indexes. Otherwise the loop can not determine how to how many times to loop for i
. The simulator also needs to handle for the case that slba_previous[nsid]
doesn't exist And there for have no i
to index.
You need to loop through the full slba_previous[id,i]
and then check if id==nsid
.
The warning is for the i+1
condition. Use the .exists()
built-in function to insure the there is an existing array entry. The design may always have an even number of entries, but it looks like QuestaSIM's constraint solver is more pessimistic and and wants to consider all possibilities.
constraint slba_nlb_non_overlapping_c
{
foreach(slba_previous[id,i])
{
if(id==nsid && (i%2)==0)
{
slba < slba_previous[id][i] -> (slba + nlb) < slba_previous[id][i];
if (slba_previous[id].exists(i+1))
{
slba > slba_previous[id][i] -> slba > slba_previous[id][i+1];
slba > slba_previous[id][i+1] -> (slba + nlb) > slba_previous[id][i+1];
slba < slba_previous[id][i+1] -> slba < slba_previous[id][i];
}
}
}
}
working example on EDA Playground
Upvotes: 1