Today, I ran across a problem where I had to compare two arrays, but the order did not matter. To further complicate things, each array was made up of structs.

I figured the easiest way to compare the two arrays was to use the built-in sort method (7.12.2 Array ordering methods in IEEE 1800-2012) to sort both arrays, then compare them one-by-one. The sort method can be used on any unpacked array except for associative arrays, such as dynamic arrays and queues.

int s[] = '{9, 1, 7};
s.sort; // s = {1, 7, 9}

string a[$] = '{"Hello", "world", "how", "are", "you?"};
a.sort; // a = {"Hello", "are", "how", "world", "you?"}

Of course, with a struct it gets a little trickier.

typedef struct {
  int a;
  string n;
} t_pkt;

t_pkt x [] = '{
  '{42, "name 0"},
  '{7,  "name 1"},
  '{0,  "name 2"}
};
initial x.sort;

Compiling this with vcs gives me an error message:

Error-[SV-MWC] Missing with clause
testbench.sv, 27
tb, "x.sort;"
  Array method 'sort' requires a with clause as it cannot be applied directly 
  to the element type.
  Object: 'x' of type: t_pkt
  Please refer to the SystemVerilog LRM (1800-2012) Section 7.12 "Array 
  manipulation methods".

So to sort the array of structs, we need to use the with clause. The expression within with tells sort how to sort the array. By default, the iterator name is item.

initial x.sort with (item.a); // x = '{'{0, "name 2"}, '{17, "name 1"}, '{42, "name 0"}}

More than one sorting condition can be used too. For example:

typedef struct {
  int a, b;
} t_y;

t_y y [] = '{
  '{42, 0},
  '{7,  0},
  '{42, 2},
  '{7,  6},
  '{0,  1}
};
initial y.sort with ({item.a, item.b}); // '{'{a:0, b:1}, '{a:7, b:0}, '{a:7, b:6}, '{a:42, b:0}, '{a:42, b:2}} 

So back to the original problem – comparing two arrays, ignoring order. This can be packaged up in a neat little function. Simply pass in two arrays (or queues), sort them both, check the sizes, then check the contents.

function compare_arrays (t_y y0 [], t_y y1 []);
  y0.sort with ({item.a, item.b});
  y1.sort with ({item.a, item.b});

  if (y0.size != y1.size) return 0;

  foreach (y0[i]) begin
    if (y0[i].a != y1[i].a) return 0;
    if (y0[i].b != y1[i].b) return 0;
  end

  return 1;
endfunction

initial begin
  t_y y0 [] = '{'{0, 0}, '{1, 1}, '{1, 2}, '{3, 2}};
  t_y y1 [] = '{'{1, 1}, '{1, 2}, '{3, 2}, '{0, 0}};
  t_y y2 [] = '{'{1, 1},          '{3, 2}, '{0, 0}};
  t_y y3 [] = '{'{0, 0}, '{1, 1}, '{1, 2}, '{3, 0}};

  $display("y0 %s y0", compare_arrays(y0, y0) ? "==" : "!=");
  $display("y0 %s y1", compare_arrays(y0, y1) ? "==" : "!=");
  $display("y0 %s y2", compare_arrays(y0, y2) ? "==" : "!=");
  $display("y0 %s y3", compare_arrays(y0, y3) ? "==" : "!=");
end

Running this results in the expected output:

y0 == y0
y0 == y1
y0 != y2
y0 != y3

The code is published to EDA Playground: Sorting arrays of structs