Part 2 · Phases & Lifecycle · Intermediate

final_phase: Last Teardown and Resource Cleanup

Top-down final_phase traversal, closing file handles, flushing coverage databases, and safe shutdown ordering.

final_phase role

The final_phase callback is the very last phase in the UVM schedule. Unlike extract/check/report, traversal is top-down : parents finalize before children. Use it to close files, flush coverage databases, release PLI handles, and perform any cleanup that must happen after all reporting is done.

diagram
[PHASE][UVM] final_phase traversal (top-down)

uvm_test (final first)
    │
    ├── tb_env
    │     ├── axi_agent
    │     └── scoreboard
    │
    └── closes shared resources, then children finalize
  • No UVM phase runs after final_phase — this is truly the end.

  • Do not raise objections or consume simulation time.

  • Idempotent close logic handles multiple final_phase calls safely.


Reference implementation

systemverilog
class my_env extends uvm_env;
  int log_fd;
  bit log_opened;

  function void final_phase(uvm_phase phase);
    super.final_phase(phase);   // children finalize first (top-down parent calls super, children run)

    if (log_opened && log_fd != 0) begin
      $fwrite(log_fd, "=== simulation complete ===
");
      $fclose(log_fd);
      log_fd = 0;
      log_opened = 0;
      `uvm_info("FINAL", "closed transaction log", UVM_MEDIUM)
    end
  endfunction
endclass
systemverilog
// Coverage DB flush (vendor-specific example pattern)
function void final_phase(uvm_phase phase);
  super.final_phase(phase);
  `uvm_info("FINAL", "flushing coverage database", UVM_MEDIUM)
  // cov_db.flush();  // tool-specific API
endfunction

Key takeaways

  • final_phase is top-down — opposite of extract/check/report.

  • Close files and flush coverage DBs here, not in report_phase.

  • Guard close operations with handle-valid checks for robustness.

Common pitfalls

  • Opening new files in final_phase for primary reporting — too late.

  • Closing shared handles in a child before parent finishes writing.

  • Skipping super.final_phase and leaving child resources open.


Cleanup checklist

diagram
[PHASE][UVM] final_phase audit

□ transaction log file handles closed
□ waveform dump controls released (if TB-owned)
□ coverage database flushed / saved
□ PLI/VPI callbacks unregistered
□ no dangling fork from run_phase (should have joined before extract)