Garbage collection
Posted by janick on July 18th, 2008
In SystemVerilog, unlike C, you don’t have to explictly free dynamically allocated class instances. Like most modern programming languages, SystemVerilog includes a garbage collector that frees memory that is no longer needed.
Although there are a few garbage collection processes out there, the lack of a root object (like the sys object in e) almost garantees that Reference Counting is used1.
To illustrate how reference counting works, consider the following code segment:
fork
while (...) begin
eth_frame pkt = new; // Line 1
scoreboard.push_back(pkt); // Line 2
...
end // Line 3
forever begin
eth_frame pkt;
pkt = rx();
if (!scoreboard[0].compare(pkt)) …
scoreboard.pop_front(); // Line 4
end
join
When the eth_frame instance gets first created on line 1, its reference count is set to “1″. When it is later added to the scoreboard on line 2, its reference count is incremented to “2″ (one for the “pkt” variable, one for the “scoreboard” queue). When the while loop iterates on line 3, the dynamic “pkt” variable disappears, reducing the reference count to 1. When the class instance is finally popped out of the scoreboard on line 4, its reference count is decremented to “0″ and its memory is garbage collected.
This usually works well until you create circular references, i.e. objects that refer to each other.
Circular references are always created whenever you introduce the concept of a “parent” object. Take a RAL model for example, an instance of the vmm_ral_reg class has a reference to its parent vmm_ral_block class instance that gets returned by the vmm_ral_reg::get_block() method. But the vmm_ral_block class instance has a reference to all of the vmm_ral_reg instances it contains, which get returned by the vmm_ral_block::get_registers() method.
That create a circular reference for every register in a block.
That means that a RAL model cannot be garbage collected. Ever.
In the case of a RAL model, that’s not a problem because it corresponds to the DUT and that DUT, being modelled using modules and interfaces, is static in nature and can never be dynamically modified.
But in the case of objects that get created in large numbers but should live only for as long as needed (such as packets or transactions who only need to live while they are processed by the DUT), then you have to be very careful to break that circular reference to enable garbage collection. Otherwise you will end up consuming an ever-increase amount of memory.
1Turns out not to be accurate. See follow-up comment.
Posted in Uncategorized | 3 Comments »





