array reduction method
systemverilog提供的这些方法可以作用于unpacked数组,将整个数组减小到一个值。内建的方法如下:
sum() | 返回数组里所有元素的和 |
---|---|
product() | 返回数组里所有元素的乘积 |
and() | 返回数组元素的与 |
or() | 返回数组中所有元素的或 |
xor() | 返回数组中所有元素的异或 |
module fixedsize_array;
//declaration of array's
int array_1[4];
int t_sum;
int t_product;
initial begin
//array initialization
array_1 = '{
1,2,3,4};
t_sum = array_1.sum(); //t_sum = 1+2+3+4
$display("Sum of array_a is \t %0d", t_sum);
t_product = array_1.product(); //t_product = 1*2*3*4
$display("product of array_1 is \t%0d", t_product);
end
endmodule
上面的例子展示了sum()和product的方法,sum是对所有元素求和,而product是对所有的元素求积。
而and,or,和xor方法,都是位操作,将所有的元素值进行按位与,按位或或者按位异或。
我们也可以使用with操作符,对数组里面的某个元素进行必要的操作。
module fixedsize_array;
//declaration of array's
int array_1[4];
int t_sum;
int t_product;
initial begin
//array initialization
array_1 = '{
1,2,3,4};
t_sum = array_1.sum with (item * 2);
//t_sum = (1*2) + (2*2) + (3*2) + (4*2)
$display("Sum of array_1 is \t %0d", t_sum);
t_product = array_1.product with (item+2);
//t_product = (1+2)*(2+2)*(3+2)*(4+2) = 3*4*5*6
$display("product of array_1 is \t %0d", t_product);
end
endmodule
在上面例子中对数组里面的元素分别进行了乘2和加2的操作。执行结果如下:
array locator method
数组定位方法对于找到一个数组元素的索引是很有帮助的。这类的方法可以操作unpacked类型的数组和队列。这些方法的返回类型是一个队列。通过一个表达式可以找到数组对应的元素或者相应的索引。因此根据找索引还是找元素,可以分类为element finder和index finder。
element finder
find() | 找到所有符合表达式的元素 |
---|---|
find_first() | 找到第一个满足表达式的元素 |
find_last() | 找到最后一个满足表达式的元素 |
min() | 找到数组里面最小的元素 |
max() | 找到数组里面最大的元素 |
unique() | 找到数组里面具有唯一值的元素 |
** index_finder**
find_index | 找到所有满足表达式元素的索引 |
---|---|
find_first_index() | 返回满足给定表达式的第一个元素的索引 |
find_last_index | 返回满足给定表达式的最后一个元素的索引 |
unique_index() | 返回具有唯一值的元素的索引 |
class packet;
int a;
int b;
function void display();
$display("\tValue of a = %0d", a);
$display("\tValue of b = %0d", b);
endfunction
endclass
module assoc_array;
//declaration of array
packet assoc_array[*] ;
packet pkt ;
int count ;
int qu[$] ;
int tmp_var ;
initial begin
pkt = new();
pkt.a = 8;
pkt.b = 3;
assoc_array[2] = pkt;
pkt = new();
pkt.a = 0;
pkt.b = 6;
assoc_array[5] = pkt;
pkt = new();
pkt.a = 2;
pkt.b = 6;
assoc_array[6] = pkt;
pkt = new();
pkt.a = 1;
pkt.b = 6;
assoc_array[9] = pkt;
//==========================================================================
//========== Find Index Method ===========
//==========================================================================
//type-1:returning one matching index
qu = assoc_array.find_index with (item.a == 'h2);
count = qu.size();
for(int i=0; i<count; i++)begin
tmp_var = qu.pop_front();
$display("Index of Asoc Array for a == 2 is %0d", tmp_var);
end
//type-2:returning multiple matching index
qu = assoc_array.find_index with (item.b == 6);
count = qu.size();
for(int i = 0; i < count; i++)begin
tmp_var = qu.pop_front();
$display("Index of Asoc Array for b==6 is %0d", tmp_var);
end
//type-3:with multiple conditions
qu = assoc_array.find_index with (item.a == 2 && item.b == 6);
count = qu.size();
for(int i = 0; i < count; i++)begin
tmp_var = qu.pop_front();
$display("Index of Asoc Array for a == 2,b==6 is %0d", tmp_var);
end
end
endmodule
在上面的代码中,类packet有两个int类型的变量,以及一个display方法打印成员的变量值。在模块assoc_array内,定义了packet类型的关联数组。声明了packet类句柄,以及int类型的count,tmp_var以及队列qu。
然后创建了3个类packet的实例,并将其赋值给关联数组元素。最后调用数组的查找方法,这个方法会返回一个队列。然后再使用队列的pop_front()方法取出队列里面的元素,打印出来。执行结果如下:
array iterator
我们可以查找一个数组中的元素或者索引,但是只能实现分别查找。使用iterator迭代器我们可以同时处理数组中的元素或索引。迭代器的简单理解可以认为是with中的item。
array_1.find with (item == item.index)
返回一个数组元素,它的值就是它的索引。
array_2.find with (item > item.index)
返回的数组元素,它的值比它的索引大。
module fixedsize_array;
//declaration of array's
int array_1[6] ;
int array_2[6] ;
int temp_qu[$] ;
int temp_cnt ;
int temp_value ;
initial begin
//array initialization
array_1 = '{
10,20,2,40,67,5};
array_2 = '{
80,4,2,40,67,5};
//type-1
temp_qu = array_1.find with (item == item.index);
temp_cnt = temp_qu.size();
$display("Index and Elements are same for %0d index's", temp_cnt);
for(int i = 0; i < temp_cnt; i++)begin
temp_value = temp_qu.pop_front();
$display("\tsame for value %0d", temp_value);
end
//type-2
temp_qu = array_1.find with (item > item.index);
temp_cnt = temp_qu.size();
$display("Index and Elements satisfied for %0d index's", temp_cnt);
for(int i = 0; i < temp_cnt; i++)begin
temp_value = temp_qu.pop_front();
$display("\t for value %0d", temp_value);
end
end
endmodule
上例中,item指代数据元素值,item.index则是元素的索引,find返回数据元素。通过item==item.index找到值和索引相等的元素,通过item>item.index找到值大于索引的元素。可见,同时使用了元素和元素索引。执行结果如下:
array slice
slice切片,对于数组而言,就是数组中连续的元素,而part select片则是选择一个元素的连续bit。
bit [31:0] data;
bit [07:0] byte[4];
byte[0] = data[07:0];
byte[1] = data[15:8];
byte[2] = data[23:16];
byte[3] = data[31:24];
如上所示,part select与verilog类似,通过索引选择8bit赋值给byte,对一个元素的单独操作。
而slice是将多个数组元素进行拆分,拆分成更小的数组,是对数组的操作。
bit [31:0] packet_type_A [7:0]; //array of 8 elements of width 32bit
bit [31:0] packet_type_B [1:0]; //array of 2 elements of width 32bit
packet_type_B = packet_type_A[5:4]; //assigning 2 elements of array packet_type_A to packet_type_B
在systemverilog中,提供了更加翻篇的片选方法。
+:NOTATION
byte = data[j += k]
其中j表示起始位,k表示总的位数。如byte = data[0 +: 8]。则是等价于byte = data[7:0]。
还可以指定最大的索引,然后通过-:设置其他索引。j依然是起始索引,k在-:依然表示k bit,但其他索引都从起始索引开始递减。如data[7-:8]等价于data[7:0]
需要指出的是,这里的j可以是变量,而k必须是常量。