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

class probe_object extends uvm_object;
  int value = 5;
  int control = 7;
  `uvm_object_utils_begin(probe_object)
    `uvm_field_int(value, UVM_NOCOPY)
    `uvm_field_int(control, UVM_ALL_ON)
  `uvm_object_utils_end
  function new(string name = "probe_object"); super.new(name); endfunction
endclass

class other_object extends uvm_object;
  `uvm_object_utils(other_object)
  function new(string name = "other_object"); super.new(name); endfunction
endclass

class quiet_object extends uvm_object;
  `uvm_object_utils(quiet_object)
  function new(string name = "quiet_object"); super.new(name); endfunction
endclass

class message_counter extends uvm_report_catcher;
  int miscompares;
  int suppressed;
  function new(); super.new("message_counter"); endfunction
  function action_e catch();
    if (get_id() == "MISCMP") miscompares++;
    if (get_id() == "NO_ACTION_PROBE") suppressed++;
    return THROW;
  endfunction
endclass

class int_sink extends uvm_component;
  `uvm_component_utils(int_sink)
  uvm_analysis_imp#(int, int_sink) imp;
  int count;
  function new(string name, uvm_component parent);
    super.new(name, parent);
    imp = new("imp", this);
  endfunction
  function void write(int value); count++; endfunction
endclass

class packed_object extends uvm_object;
  `uvm_object_utils(packed_object)
  function new(string name = "packed_object"); super.new(name); endfunction
  function void do_pack(uvm_packer packer);
    packer.pack_field_int(8'h96, 8);
    packer.pack_string("A");
  endfunction
endclass

module policy_probe;
  initial begin
    probe_object a = new("a"), b = new("b");
    quiet_object q = new("q");
    other_object o = new("o");
    message_counter catcher = new();
    uvm_comparer cmp = new();
    uvm_resource_pool pool = uvm_resource_pool::get();
    uvm_resource#(int) resource_a, resource_b, selected;
    uvm_tlm_fifo#(int) fifo = new("fifo", null, 8);
    int_sink sink = new("sink", null);
    uvm_report_object reporter = new("reporter");
    packed_object packed_value = new();
    uvm_packer packer;
    bit stream[];
    string bits_text;
    int count, before_count;
    bit same;
    mailbox#(int) mailbox_probe = new();
    int mailbox_value, mailbox_status;
    int drained_value, drained_count;
    uvm_resource_types::rsrc_q_t resources;
    uvm_resource_base winner;

    #1;
    uvm_report_cb::add(null, catcher);
    uvm_root::get().set_report_verbosity_level(UVM_LOW);
    b.value = 123;
    cmp.verbosity = UVM_HIGH;
    same = a.compare(b, cmp);
    $display("REVIEW|negative_field_equal|%0d", same);
    b.copy(a);
    $display("REVIEW|negative_field_copy|%0d", b.value);

    cmp.check_type = 0;
    same = q.compare(o, cmp);
    $display("REVIEW|explicit_comparer_check_type|%0d", cmp.check_type);
    $display("REVIEW|explicit_comparer_equal|%0d", same);
`ifdef REVIEW_UVM20
    cmp.flush();
    cmp.set_check_type(0);
    same = cmp.compare_object("pair", q, o);
`else
    cmp.check_type = 0;
    same = q.compare(o, cmp);
`endif
    $display("REVIEW|migrated_comparer_equal|%0d", same);

    cmp.show_max = 0;
    cmp.verbosity = UVM_NONE;
    cmp.result = 0;
    before_count = catcher.miscompares;
    same = cmp.compare_field_int("field", 1, 2, 32);
    $display("REVIEW|show_max_zero_messages|%0d", catcher.miscompares - before_count);
    cmp.verbosity = UVM_HIGH;
    before_count = catcher.miscompares;
    same = cmp.compare_field_int("quiet_field", 1, 2, 32);
    $display("REVIEW|quiet_comparer_messages|%0d", catcher.miscompares - before_count);

    uvm_resource_base::default_precedence = 4321;
    resource_a = new("priority_probe", "env.*");
    resource_a.write(11);
    $display("REVIEW|constructed_precedence|%0d", resource_a.precedence);
    pool.set(resource_a);
    $display("REVIEW|registered_precedence|%0d", resource_a.precedence);
`ifdef REVIEW_UVM20
    $display("REVIEW|pool_default|%0d", pool.get_default_precedence());
    $display("REVIEW|pool_precedence|%0d", pool.get_precedence(resource_a));
`endif
    $display("REVIEW|constructor_scope_match|%0d", resource_a.match_scope("env.agent"));
    resource_b = new("priority_probe", "env.*");
    resource_b.write(22);
    pool.set(resource_b);
    resource_a.precedence = 9999;
    $display("REVIEW|direct_precedence_values|%0d:%0d", resource_a.precedence, resource_b.precedence);
    resources = pool.lookup_name("env.agent", "priority_probe", uvm_resource#(int)::get_type());
    winner = pool.get_highest_precedence(resources);
    $display("REVIEW|highest_is_first|%0d", winner == resource_a);
    selected = uvm_resource_db#(int)::get_by_name("env.agent", "priority_probe");
    $display("REVIEW|direct_precedence_winner|%0d", selected.read());
`ifdef REVIEW_UVM20
    uvm_resource_pool::set_default_precedence(2468);
    resource_a = new("migrated_priority");
    pool.set_scope(resource_a, "env.*");
`else
    uvm_resource_base::default_precedence = 2468;
    resource_a = new("migrated_priority", "env.*");
    resource_a.set();
`endif
    $display("REVIEW|migrated_precedence|%0d", resource_a.precedence);

    reporter.set_report_id_action("NO_ACTION_PROBE", UVM_NO_ACTION);
    `uvm_info_context("NO_ACTION_PROBE", "suppressed", UVM_NONE, reporter)
    $display("REVIEW|no_action_catcher|%0d", catcher.suppressed);

    fifo.get_ap.connect(sink.imp);
    fifo.get_ap.resolve_bindings();
    same = fifo.try_put(11);
    $display("REVIEW|fifo_first_put|%0d:%0d", same, fifo.used());
    same = fifo.try_put(22);
    $display("REVIEW|fifo_second_put|%0d:%0d", same, fifo.used());
    fifo.flush();
    $display("REVIEW|fifo_flush_broadcast|%0d", sink.count);
    $display("REVIEW|fifo_flush_used|%0d", fifo.used());
    drained_count = 0;
    while (fifo.try_get(drained_value)) drained_count++;
    $display("REVIEW|explicit_drain_used|%0d", fifo.used());
    mailbox_probe.put(11);
    mailbox_probe.put(22);
    mailbox_status = mailbox_probe.try_get(mailbox_value);
    $display("REVIEW|mailbox_try_get|%0d:%0d:%0d", mailbox_status, mailbox_value, mailbox_probe.num());
    mailbox_status = mailbox_probe.try_get(mailbox_value);
    $display("REVIEW|mailbox_try_get_last|%0d:%0d:%0d", mailbox_status, mailbox_value, mailbox_probe.num());

    packer = new();
    count = packed_value.pack(stream, packer);
    bits_text = "";
    foreach (stream[i]) bits_text = {bits_text, stream[i] ? "1" : "0"};
    $display("REVIEW|native_pack|%0d:%s", count, bits_text);
`ifdef REVIEW_UVM20
    begin
      uvm_compat_packer legacy = new();
      packer = legacy;
    end
`endif
    count = packed_value.pack(stream, packer);
    bits_text = "";
    foreach (stream[i]) bits_text = {bits_text, stream[i] ? "1" : "0"};
    $display("REVIEW|compat_pack|%0d:%s", count, bits_text);
    $display("REVIEW|done|1");
    $finish;
  end
endmodule
