Gotcha: Access an out of Bounds Index for a SystemVerilog Fixed Size Array

I came across a SystemVerilog coding scenario where extra precaution needs to be taken when accessing fixed size arrays. The scenario was about accessing an invalid index in a fixed size array. SystemVerilog defines invalid index values as such: ‘X’ (undefined), ‘Z’ (high impedance), a value higher than the array’s size or a negative value. Using such an invalid index for reading an array element, should return the default value of the element’s type.

This gotcha is best understood if we consider a piece of code like the one bellow:

class out_of_bounds#(type T=int, int S=1);
  T an_array[S];

  function new(T init_array[S]);
    an_array = init_array;		
  endfunction
	
  function void read(integer idx);
    $display("Reading from index %p, value is:%p", idx, an_array[idx]);
  endfunction

  function void write(integer idx, T value);
    an_array[idx] = value;
    $display("Writing to index %p, value is:%p", idx, value);
  endfunction
endclass

module top;
  out_of_bounds#(int,3) int_i;
  out_of_bounds#(string,3) string_i;

  initial begin
    int_i = new({1,2,3});
    string_i = new({"s1","s2","s3"});
	
    int_i.write('z, 77);
    string_i.write('z, "out_of_bounds");
		
    int_i.read('z);
    string_i.read('z);

    int_i.read(-2);
    string_i.read(-2);
		
    int_i.read(100);
    string_i.read(100);
  end
endmodule

The standard recommends to issue a warning but it does not impose it, as found in SystemVerilog IEEE Std 1800-2012 Language Reference Manual, chapter “7.4.6 Indexing and slicing of arrays”:

If an index expression is out of bounds or if any bit in the index expression is x or z, then the index shall be invalid. Reading from an unpacked array of any kind with an invalid index shall return the value specified in Table 7-1. Writing to an array with an invalid index shall perform no operation, with the exceptions of writing to element [$+1] of a queue (described in 7.10.1) and creating a new element of an associative array (described in 7.8.6). Implementations may issue a warning if an invalid index occurs for a read or write operation on an array.

According to the above statement the output of the code should look like this:

Writing to index z, value is:77
Writing to index z, value is:"out_of_bounds"
Reading from index z, value is:0
Reading from index z, value is:""
Reading from index -2, value is:0
Reading from index -2, value is:""
Reading from index 100, value is:0
Reading from index 100, value is:""

Knowing what the standard recommends, try to run that code with your simulator. You might find yourself in one of the following scenarios:

  • [Standard recommendation] Reading from an unpacked array of any kind with an invalid index shall return the data type default value (0 for int, “” for strings, etc.)
  • [Buggy behaviour in my opinion] accessing the index ‘Z’ is actually modifying the first element in the list, since ‘Z’ is “transformed” internally into 0. Thus, reading the array index ‘Z’ returns the value 77 instead of 0.
  • Accessing a string array element using an invalid index returns a run-time error
  • You will get a compile warning if the simulator detects a constant used as (out of bounds) array index

The above was tested using fixed size arrays. What about a dynamic array or a queue? Try it out yourself and see which one applies for your simulator. I found these various behaviours:

  • warnings for the write operations, but quiet for read operations.
  • warnings only when writing an out of bounds element for a queue, otherwise silent
  • warnings for the read operation but silent for the write operations.

In conclusion, be extra careful with index accessing because most of the times you will not be warned that you’re doing something wrong.


Comments

Leave a Comment:

Your comment will be visible after approval.

(will not be published)

This site uses Akismet to reduce spam. Learn how your comment data is processed.