SystemVerilog OOP Mastery · All levels

Callbacks and Policy Classes for Open Extension: Code Examples

Code Examples for Callbacks and Policy Classes for Open Extension.

Code examples

Driver callback hook around pin-driving logic

systemverilog
class drv_cb extends uvm_callback;\n  virtual task pre_drive(my_item t); endtask\n  virtual task post_drive(my_item t); endtask\nendclass\n\nclass my_driver extends uvm_driver #(my_item);\n  `uvm_component_utils(my_driver)\n  `uvm_register_cb(my_driver, drv_cb)\n\n  virtual task run_phase(uvm_phase phase);\n    my_item req;\n    forever begin\n      seq_item_port.get_next_item(req);\n      `uvm_do_callbacks(my_driver, drv_cb, pre_drive(req))\n      drive_item(req);\n      `uvm_do_callbacks(my_driver, drv_cb, post_drive(req))\n      seq_item_port.item_done();\n    end\n  endtask\nendclass

The driver owns protocol timing; callbacks layer extra actions without creating another driver subclass for each variation.

Policy class used by scoreboard comparison

systemverilog
virtual class compare_policy;\n  pure virtual function bit match(my_item exp, my_item got);\nendclass\n\nclass strict_compare_policy extends compare_policy;\n  virtual function bit match(my_item exp, my_item got);\n    return (exp.addr == got.addr) && (exp.data == got.data);\n  endfunction\nendclass\n\nclass masked_compare_policy extends compare_policy;\n  bit [31:0] data_mask = 32'hFFFF_FF00;\n  virtual function bit match(my_item exp, my_item got);\n    return (exp.addr == got.addr) &&\n           ((exp.data & data_mask) == (got.data & data_mask));\n  endfunction\nendclass

The scoreboard can switch between strict and masked semantics without changing class hierarchy.

Inject policy through config_db in build_phase

systemverilog
class my_scoreboard extends uvm_component;\n  `uvm_component_utils(my_scoreboard)\n  compare_policy policy;\n\n  function void build_phase(uvm_phase phase);\n    super.build_phase(phase);\n    if (!uvm_config_db#(compare_policy)::get(this, "", "policy", policy))\n      policy = strict_compare_policy::type_id::create("policy");\n  endfunction\nendclass\n\nclass debug_test extends uvm_test;\n  `uvm_component_utils(debug_test)\n  function void build_phase(uvm_phase phase);\n    compare_policy p;\n    super.build_phase(phase);\n    p = masked_compare_policy::type_id::create("p");\n    uvm_config_db#(compare_policy)::set(this, "env.scb", "policy", p);\n  endfunction\nendclass

Policy injection is explicit in hierarchy and can vary per test path, which improves debuggability compared with hidden globals.

Related topics