Associative arrays

动态数组用于处理数量动态变化的连续变量集合。当集合的大小未知或数据空间稀疏时,关联数组是更好的选择。关联数组在使用之前不分配任何存储,索引表达式不限于整型表达式,可以是任何类型的。关联数组实现了声明其类型元素的查找表。作为索引的数据类型会被强制排序并用于查找的关键词。
声明关联数组的语法如下:

data_type array_id [ index_type ];
//其中,data_type 为数组元素的数据类型。可以允许使用任何类型固定大小的数组
//     array_id为要声明的数组的名称
//	   index_type是要用作索引的数据类型,或者是*。如果指定了*,
//	   则数组被任意大小的整数表达式索引。索引类型将索引表达式限制为特定类型。index_type声明类型是非法的。

关联数组声明的例子如下:

integer i_array[*];			 // associative array of integer (unspecified
							// index)
bit [20:0] array_b[string]; // associative array of 21-bit vector, 
							// indexed by string
event ev_array[myClass]; 	// associative array of event indexed by class
							// myClass

1.声明
通过方括号中放置数据类型实现 int data_as[bit [31:0]] : int为存储数据类型,bit[63:0]为寻址的类型.
2.初始化
关联数组初始化时使用 : '{};在大括号内写入键值对的信息,键值对用:连接;
data_as = '{1:20,2:21,3:22};

关联数组中的数组元素是动态分配的。当一个不存在的关联数组元素被用作赋值的目标或通过引用传递的实参的实参时,它应该被分配。关联数组根据索引数据类型维护已赋值的项及其相对顺序。关联数组元素被解包。换句话说,除了用于复制或比较数组之外,必须先从数组中选择单个元素,然后才能在大多数表达式中使用该元素。

1、通配符索引类型

例如:

int array_name [*];

指定通配符索引类型的关联数组具有以下属性:

  • 数组可以用任何整数表达式建立索引。因为索引表达式的大小可能不同,所以相同的数值可以有多个表示,每个表示的大小不同。SystemVerilog通过删除前导零并计算最小长度并使用该值表示来解决这种模糊性。
  • 非整数索引值是非法的,会导致错误。
  • 包含X或Z的4状态索引值无效
  • 自定索引表达式被视为无符号类型。
  • 字符串索引会自动转换为大小相等的位向量。
  • 排序是数字的(从最小到最大)。
  • 对于返回索引值或值数组的数组操作方法,不应在foreach循环中使用指定通配符索引类型的关联数组。指定通配符索引类型的关联数组不应在foreach循环中使用,也不应与返回索引值或值数组的数组操作方法一起使用。

2、字符串索引

例如:

int array_name [ string ];

字符串索引的关联数组具有以下属性:

  • 索引可以是任意长度的字符串或字符串文字。其他类型是非法的,将导致类型检查错误
  • 空字符串" "索引是有效的。
  • 顺序是按字典顺序排列的(从小到大)

3、 类索引

例如:

int array_name [ some_Class ];

类索引的关联数组具有以下属性:

  • 索引可以是该特定类型的对象,也可以是从该类型派生的对象。任何其他类型都是非法的,将导致类型检查错误
  • 空索引是有效的。
  • 顺序是确定的,但也是随意的。

4、 整型索引

例如:

int array_name1 [ integer ];
typedef bit signed [4:1] SNibble;
int array_name2 [ SNibble ];
typedef bit [4:1] UNibble;
int array_name3 [ UNibble ];

一个整型数据类型的索引的关联数组应具有以下属性

  • 索引表达式应根据对索引类型的转换进行评估,但从real或shortreal数据类型的隐式转换是非法的。
  • 含有X或Z的四态索引表达式无效
  • 排序是有符号或无符号数字,取决于索引类型的符号性

5、 其他用户定义的类型

例如:

typedef struct {byte B; int I[*];} Unpkt;
int array_name [ Unpkt ];

一般来说,指定任何类型的索引的关联数组具有以下属性:

  • 声明的索引应具有等于运算符,其类型才是合法的。这包括所有动态大小的类型作为合法的索引类型。但是real和shortreal数据类型,或包含real或shortreal的类型,是一个非法的索引类型
  • 一个索引表达式如果是或在其任何元素中包含X或Z是无效的。
  • 一个索引表达式,如果它的任何元素是或包含一个空值或空,并不会使索引无效
  • 如果关系运算符是为索引类型定义的,那么排序就像前面定义的那样。如果没有,这样一个关联数组中任何两个条目的相对排序都可以改变,甚至在同一工具的连续运行之间也可以改变。但是,在同一模拟运行中,如果没有添加或删除任何索引,相对顺序应保持不变。

6、访问无效的索引

如果读操作使用的索引是带有一个或多个x或z位的4态表达式,或者试图读取一个不存在的类型,那么将发出警告,并返回该阵列类型的不存在的类型值,如表所示:

systemverilog关联数组的直接赋值 verilog 关联数组_ci

7、关联数组元素的分配

当一个不存在的关联数组元素被用作赋值的目标或实际到一个通过引用传递的参数时,它的条目应被分配。一些结构体在单个语句中同时执行读和写操作,比如说自增运算。在这些情况下,不存在的元素应在对该元素的任何引用之前分配其默认或用户指定的初始值。
例如:

int a[int] = '{default:1}; 
typedef struct { int x=1,y=2; } xy_t; 
xy_t b[int]; 
begin 
a[1]++; 
b[2].x = 5;
end

假设对a[1]和b[2]的引用在这些语句执行之前是不存在的元素。在执行a[1]++时,a[1]将被分配并初始化为1。在自增运算之后,a[1]将是2。在执行b[2].x=5时,b[2]将被分配,b[2].x将为1,b[2].y将为2。执行赋值后,b[2].x将被更新为5。

Associative array 初始化方法和内置方法1.声明

1.关联数组的大小(num|size)

可以使用size()、num()来实现;没有写入数据时,大小为0

function int num();
function int size();

int imem[int];
imem[ 3 ] = 1;
imem[ 16'hffff ] = 2;
imem[ 4'b1000 ] = 3;
$display( "%0d entries\n", imem.num ); // prints "3 entries"

2.关联数组的删除(delete)

在使用delete函数时,如果里面给了索引值,如果索引值存在,那么将相应的键值对删除;否则,什么都不做.如果没有给索引值,那么将整个关联数组删除.

function void delete( [input index] ); // index is an optional index of the appropriate type for the array in question.
int map[ string ];
map[ "hello" ] = 1;
map[ "sad" ] = 2;
map[ "world" ] = 3;
map.delete( "sad" ); // remove entry whose index is "sad" from "map"
map.delete; // remove all entries from the associative array "map"

3.关联数组Exists()

exists函数用来判断对应的索引值是否存在,存在则返回1,不存在则返回0

function int exists( input index ); //index is an index of the appropriate type for the array in question

if ( map.exists( "hello" ))
map[ "hello" ] += 1;
else 
map[ "hello" ] = 0;

4.关联数组First()与next()

first返回最小的索引值;如果数组是空的,函数返回0;否则,函数返回1。
next返回数值大于给定索引参数的最小索引。如果下一个不存在,函数返回0;否则,函数返回1。
first常与next配合使用实现关联数组的遍历;

function int first( ref index ); //index is an index of the appropriate type for the array in question
function int next( ref index ); //index is an index of the appropriate type for the array in question

data_as = '{1:20,2:21,3:22};
if(data_as.first(data_index))begin
do
begin $display(“data_as[0x%0h] is 0x%0h”,data_index,data_as[data_index]);
end
while(data_as.next(data_index));
end
data_as[0x0] is 0x14
data_as[0x1] is 0x15
data_as[0x2] is 0x16

5.关联数组last()和prev()

last返回最大的索引值;prev返回比给定的索引值小的最大索引值; 二者配合使用实现关联数组的遍历;

function int prev( ref index ); 
function int last( ref index ); 

data_as = '{1:20,2:21,3:22};
if(data_as.last(data_index))begin
do
begin $display(“data_as[0x%0h] is 0x%0h”,data_index,data_as[data_index]);
end
while(data_as.prev(data_index));
end
data_as[0x2] is 0x16
data_as[0x1] is 0x15
data_as[0x0] is 0x14