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\nendclass

Choose 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\nendclass

Parameterized type syntax can make wrappers look isolated, but handle aliasing still follows normal reference semantics.

Related topics