SystemVerilog OOP Mastery · All levels
Static and Parameterized Gotchas: Code Examples
Code Examples for Static and Parameterized Gotchas.
Code examples
Static counter shared unintentionally
systemverilog
class txn_base;\n static int next_id = 0;\nendclass\n\nclass pkt #(type T = int) extends txn_base;\n int id;\n function new();\n // BUG: all T specializations consume the same counter.\n id = next_id++;\n endfunction\nendclass\n\npkt#(int) a = new(); // id 0\npkt#(byte) b = new(); // id 1 (surprising if per-T was intended)\n\nclass pkt_fix #(type T = int);\n static int next_id = 0;\n int id;\n function new();\n // FIX: static lives inside parameterized class, so per specialization.\n id = next_id++;\n endfunction\nendclassChoose static placement intentionally. Base static means global sharing; parameterized class static means per-specialization sharing.
Shallow clone in parameterized wrapper aliases payload
systemverilog
class payload;\n int words[];\nendclass\n\nclass box #(type T = payload);\n T item;\n function new();\n item = new();\n endfunction\n\n function box#(T) clone_bug();\n box#(T) c = new();\n // BUG: shallow copy, both wrappers share one payload object.\n c.item = this.item;\n return c;\n endfunction\n\n function box#(T) clone_fix();\n box#(T) c = new();\n // FIX: deep-copy payload fields.\n c.item = new();\n c.item.words = new[this.item.words.size()];\n foreach (this.item.words[i])\n c.item.words[i] = this.item.words[i];\n return c;\n endfunction\nendclassParameterized type syntax can make wrappers look isolated, but handle aliasing still follows normal reference semantics.