I've recently transitioned from Specman/e to SystemVerilog and I'm struggling with the limitations of the array methods in SystemVerilog. I have an array of class objects, which themselves have an array of class objects inside each one. I want to check if the array has an item, whose sub-array has an item with a certain value. In Specman this would be simple as so:
struct axi_beat_s {
addr : int;
};
struct axi_trans_s {
beat_list : list of axi_beat_s;
};
var axi_trans_list : list of axi_trans_s;
//Populate axi_trans_list, not shown here
//Check if the axi trans list has a trans with a beat with address 0
if (axi_trans_list.has(it.beat_list.has(it.addr == 0))) { //This is the line I want to replicate
//do something
} else {
//do something else
};
What is the best way to achieve the same in SystemVerilog? This is my attempt below, but it involves creating 2 temporary arrays, and several more lines of code. Is there an easier way of doing this?
class axi_beat_s;
int addr;
endclass
class axi_trans_s;
axi_beat_s beat_list [$];
endclass
axi_trans_s axi_trans_list [$];
//Populate axi_trans_list, not shown here
axi_trans_s axi_trans_list_temp [$];
axi_beat_s axi_beat_list_temp [$];
foreach(axi_trans_list[idx]) begin
axi_beat_list_temp = axi_trans_list[idx].beat_list.find with (item.addr == 0);
if (axi_beat_list_temp.size() > 0)
axi_trans_list_temp.push_back(axi_trans_list[idx]);
if (axi_trans_list_temp.size() > 0)
$display("Found item with addr 0");
else
$display("Did not find item with addr 0");
end
Working example here: https://www.edaplayground.com/x/RFEk
Similarly Specman has a method 'all' which can be used to collect all matching items, similar to 'find' in SystemVerilog. But again, I can't find based on a nested class object.
CodePudding user response:
You want to use the array reduction methods, not the find
method.
The find
method returns an array of the same type with the selected set of elements—it cannot be nested. If you just want to get a true or false result, the array reduction methods return a single value and can be nested.
initial begin
// populate list not shown here
if (axi_trans_list.or() with (item.beat_list.or() with (item.addr==0)))
$display("Found item with addr 0");
else
$display("Did not find item with addr 0");
end