`timescale 1ns/1ps
`include "uvm_macros.svh"
import uvm_pkg::*;

class extension_checks;
  static int calls;
endclass

class extension_a extends uvm_tlm_extension#(extension_a);
  `uvm_object_utils(extension_a)
  function new(string name = "extension_a"); super.new(name); endfunction
  function bit do_compare(uvm_object rhs, uvm_comparer comparer);
    extension_checks::calls++;
    return 1;
  endfunction
endclass

class extension_b extends uvm_tlm_extension#(extension_b);
  `uvm_object_utils(extension_b)
  function new(string name = "extension_b"); super.new(name); endfunction
  function bit do_compare(uvm_object rhs, uvm_comparer comparer);
    extension_checks::calls++;
    return 1;
  endfunction
endclass

class probe_payload extends uvm_tlm_generic_payload;
  function new(string name); super.new(name); endfunction
  function void remove_last_extension();
    uvm_tlm_extension_base key;
    if (m_extensions.last(key)) m_extensions.delete(key);
  endfunction
  function bit extensions_equal(probe_payload rhs, uvm_comparer comparer);
    if (m_extensions.num() != rhs.m_extensions.num()) return 0;
    foreach (m_extensions[key]) begin
      if (!rhs.m_extensions.exists(key)) return 0;
      if (!m_extensions[key].compare(rhs.m_extensions[key], comparer)) return 0;
    end
    return 1;
  endfunction
endclass

class legacy_arbitrator extends uvm_sequencer#(uvm_sequence_item);
  function new(string name, uvm_component parent); super.new(name, parent); endfunction
`ifdef REVIEW_UVM20
  virtual function int user_priority_arbitration(int avail_sequences[$]);
`else
  virtual function integer user_priority_arbitration(integer avail_sequences[$]);
`endif
    return avail_sequences[$];
  endfunction
endclass

module semantic_probe;
  initial begin
    uvm_event event_value = new("event_value");
    uvm_sequence_item object_value = new("object_value");
    probe_payload lhs = new("lhs"), rhs = new("rhs");
    extension_a a = new(), a2 = new();
    extension_b b = new(), b2 = new();
    legacy_arbitrator arbitrator = new("arbitrator", null);
    uvm_sequencer_base base_arbitrator = arbitrator;
`ifdef REVIEW_UVM20
    int available[$] = '{2, 7};
`else
    integer available[$] = '{2, 7};
`endif
    uvm_comparer comparer = new();
    uvm_cmdline_processor cmdline = uvm_cmdline_processor::get_inst();
    string matching_args[$];
    bit equal;
    int count;

    event_value.trigger(object_value);
    event_value.reset();
    $display("REVIEW|reset_keeps_data|%0d", event_value.get_trigger_data() == object_value);
    count = cmdline.get_arg_matches("/^\\+REVIEW_ARG=(red|green)[0-9]+$/", matching_args);
    $display("REVIEW|command_regex_count|%0d", count);
`ifdef UVM_VERSION_1_2
    $display("REVIEW|version_12_macro|1");
`else
    $display("REVIEW|version_12_macro|0");
`endif
    comparer.verbosity = UVM_DEBUG;
    void'(rhs.set_extension(a));
    equal = lhs.compare(rhs, comparer);
    $display("REVIEW|rhs_only_extension_equal|%0d", equal);
    equal = rhs.compare(lhs, comparer);
    $display("REVIEW|lhs_only_extension_equal|%0d", equal);
    void'(lhs.set_extension(a2));
    void'(lhs.set_extension(b2));
    void'(rhs.set_extension(b));
    extension_checks::calls = 0;
    equal = lhs.compare(rhs, comparer);
    $display("REVIEW|two_extension_equal|%0d", equal);
    $display("REVIEW|extension_compare_calls|%0d", extension_checks::calls);
    rhs.remove_last_extension();
    equal = lhs.compare(rhs, comparer);
    $display("REVIEW|missing_last_extension_equal|%0d", equal);
    $display("REVIEW|checked_extensions_equal|%0d", lhs.extensions_equal(rhs, comparer));
    $display("REVIEW|migrated_override_result|%0d", base_arbitrator.user_priority_arbitration(available));
    $display("REVIEW|done|1");
    $finish;
  end
endmodule
