Thursday, April 4, 2013

Dynamic Arrays


Why Dynamic Arrays

      Verilog allows one-dimensional arrays of variables all along and Verilog-2001 allows multi-dimensional ones too. SystemVerilog classifies an array as 'packed' or 'unpacked' depending on how it is declared. If the array upper and lower bounds are declared between the variable type and the variable name, such as

reg [7:0] a_reg_array;
The array is called packed. If the array bounds are declared after the variable name, it is called an unpacked array, such as,
int int_array [7:0];
Of course, an array may have both packed and unpacked parts.
reg [7:0] reg_array [3:0][7:0];

Whether you are declaring packed or unpacked arrays of whatever dimensions, one thing that remains common is they are all static declarations. Once an array is declared this way, the tool that parses the declaration will statically allocate memories for the array and there is no way that you can alter that afterwards. As a result, the size of an array, for example, cannot be changed once it is declared.
There are occasions, however, when you would want to declare an array whose size cannot be pre-determined. A temporary buffer for variable rate incoming data stream, a list that has variable number of elements are few examples of problems that need array size that needs to be changed dynamically. Using a very large array with the assumption that it can hold the largest data (yet whose size is unknown) is neither safe nor efficient. So, the question is how can we declare an array whose size is dynamically alterable?
SystemVerilog dynamic array type addresses this need. In a sense, dynamic arrays are equivalent of malloc library function in C that allows one to dynamically alter the size of an array (or pointer).

Declaring a Dynamic Array

            A dynamic array lets you keep the number of elements in the array unspecified at the declaration time. You can define the number of elements it holds during run time. Moreover, once declared, the number of elements can be altered at a later point of time too.
However, these benefits come at a price. There are some limitations on dynamic arrays. These limitations are:
The dynamic part of the array must be of unpacked nature. A packed array cannot be dynamic (can you guess why?)
The unpacked (and dynamic) part of the array must be one dimensional. More than one dimension is not allowed for dynamic arrays.
With this rules and regulations, here is the syntax for declaration for dynamic array:
data_type array_name [];
Note the empty square brackets ([]) that indicate that the array is dynamic. Here are some examples of dynamic array declaration (similar to static arrays declared above):
reg [7:0]      a_reg_array []; // dynamic array of 8 bit reg
reg [7:0][3:0] b_reg_array []; // dynamic array of two packed dimension
int int_array   []; // dynamic array of integers

Several things are noteworthy above.
The variable a_reg_array is dynamic only in its unpacked part. The packed part is still static (and 8 bit wide) showing mixing static packed and dynamic unpacked parts is okay.
The variable b_reg_array even has two dimensions in its packed part. It is only the unpacked part that is one-dimensional.
The variable int_array shows a case whose packed part is not an array.
Working with Dynamic Arrays
Once you have declared a dynamic array, there are few built-in operator and methods that you can use that help you to use the array effectively. These are
The new[] operator.
The size() built-in method.
The delete() built-in method.

The new[] Operator

The new[] operator creates or modifies the depth of an array. Consider the following example:
 
int int_array[]; // declare an integer array
...
int_array = new[25]; // creates 25-deep array 
In the above example, after the declaration of int_array no space has been allocated for it and hence using any array element is illegal. The memory allocation for the elements are not done until the new operator is encountered. At this point, it is legal to use the array indexes 0 through 24.
Another use of the new[] operator is to modify an existing dynamic array. In the following example, int_array2 is a second dynamic array.
 
// Declare an integer array
int int_array[];
// Declare another integer array
int int_array2[]; 
...
// Creates 25-deep array for int_array
int_array = new[25];
...
// Creates 50-deep array for int_array2
// and then copies first 25 elements from int_array
int_array2 = new[50](int_array);
In the above example, the last line indicates how new[50] creates an array of 50 elements for int_array2. Then the (int_array) part copies the existing int_array into first 25 locations of int_array2. Rest 25 locations of int_array will remain empty.
What will happen if int_array2 has less number of elements, say 15, than int_array? In that case, only the first 15 elements of int_array will be copied to int_array2.
A clever use of the new[] operator in the above manner lets you modify the size of an existing dynamic array.
 
// declare an integer array
int int_array[];
...
// creates a 25-deep array
int_array = new[25]; 
...
// deletes the last 10 elements 
int_array = new[15](int_array); 
...
// increases the size of int_array to 30
// preservng the old values
int_array = new[30](int_array); 

The method size()

The method size() returns the current size of a dynamic array as an integer.
int current_size;
...
current_size = int_array.size();
If a dynamic array is not created yet, then the returned size will be zero.

The method delete()

The method delete() simply deletes all the elements of a synamic array and leaves it at the state of declaration when the array was not created.
int_array.delete();
The size of a deleted dynamic array, as can be expected, is zero.



No comments: