Search code examples
arraysgarbage-collectionassociative-arraysystem-verilogdynamic-arrays

SystemVerilog: Are dynamic arrays (inside classes) guaranteed to be garbage-collected once the class-object is not referenced anymore?


So my question is: the "Title" and what are the garbage collection rules for dynamic arrays in SystemVerilog?

Context:

In my program, I found a bug where you can instantiate a dynamic array in a function (locally) and add elements to that array within that function, but if you don't delete the array, the entries remain there (i.e. memory and reference is preserved). So when you call the function again, all the entries that were previously entered can be accessed. The solution is to simply delete the dynamic array before you exit the function. I am assuming the array isn't deleted because the array is instantiated on the Heap instead of the Stack, and the compiler doesn't know when to garbage collect it because it could be a returned reference (please correct me if I am wrong - I am not familiar with the garbage collection rules for dynamic arrays).

However, what happens if the dynamic array is instantiated within a class (as a member variable)? How do you know if the dynamic array is deleted (i.e. reference and memory is removed)? What are the garbage collection rules for that case?

I have example code to demonstrate the issue if it is helpful but I don't think it is necessary to include it (let me know if you'd like an example). P.S. The same thing happens for associative-arrays as well (because I think it is a form of dynamic array type in SystemVerilog).

Thanks!


Solution

  • SystemVerilog has three different kinds of variable lifetimes:

    • static -- exists for the entire life of the simulation. Initilized once at time 0. Can be referenced from outside the scope of where it's declared
    • automatic -- a new instance gets created and initialized for each entry to the scope where it is declared (must be a procedural scope). Its lifetime ends when exiting the scope, and all nested scopes exit (to handle fork/join_none) Can only be referenced from within the scope where it is declared
    • dynamic -- created by the execution of a procedural statement. It's lifetime can end a number of ways, but normally by executing a procedural statement.

    Dynamically sized arrays have a compound concept of lifetimes. Individual elements have dynamic lifetimes, but the array as a whole aggregate can have any of the above lifetimes. For the purposes of your question, I think we can just consider the array as an aggregate. That means whenever the lifetime of an array variable ends, all the dynamically allocated elements are reclaimed

    Class objects have dynamic lifetimes, but the class variables that hold handles referencing class objects can any of the above lifetimes. But since more than one class variable can reference the same class object, the lifetime of class object ends when there are no more class variables referencing that object. So if that class object contains dynamic array variables, those variables lifetime end when the objects lifetime ends.

    SystemVerilog doesn't specify how garbage collection works. When the lifetime of something ends, you can no longer access it. There is no way to know when the memory actually gets reclaimed.

    Your problem seems like you have a statically declared dynamic array inside a function, or a static function argument. In Verilog, all non-class functions have static lifetimes by default. Class methods can only have automatic lifetimes. If this explanation does not answer your question, you'll need to post some code.


    BTW, this became the subject of my DVCon 2021 Paper and Presentation