systemverilog学习 --- 数组操作(二)

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必须是常量。

猜你喜欢

转载自blog.csdn.net/weixin_45614076/article/details/126504032