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

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

class guidance_reader extends uvm_component;
  function new(string name, uvm_component parent); super.new(name, parent); endfunction
endclass

class partial_flag_packet extends uvm_object;
  int value;
  `uvm_object_utils_begin(partial_flag_packet)
    `uvm_field_int(value, UVM_COPY)
  `uvm_object_utils_end
  function new(string name="partial_flag_packet"); super.new(name); endfunction
endclass

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

module guidance_probe;
  initial begin
    guidance_reader reader = new("reader", null);
    guidance_config original = new(), saved, first, second;
    uvm_object stored, first_object, second_object;
    uvm_bitstream_t wide;
    int narrow;
    bit found;
    partial_flag_packet partial_a = new(), partial_b = new();
    explicit_flag_packet explicit_a = new(), explicit_b = new();
    #1;
    original.value = 42;
`ifdef REVIEW_UVM20
    uvm_root::get().set_config_int("reader", "wide", 64'h1234567801234567);
    uvm_root::get().set_config_object("reader", "cfg", original, 1);
`else
    uvm_pkg::set_config_int("reader", "wide", 64'h1234567801234567);
    uvm_pkg::set_config_object("reader", "cfg", original, 1);
`endif
    found = uvm_config_db#(uvm_bitstream_t)::get(reader, "", "wide", wide);
    $display("REVIEW|wide_found|%0d", found);
    $display("REVIEW|wide_value|%016h", wide[63:0]);
    $display("REVIEW|wrong_int_type_found|%0d", uvm_config_db#(int)::get(reader, "", "wide", narrow));
    original.value = 99;
    found = uvm_config_db#(uvm_object)::get(reader, "", "cfg", stored);
    if (!found || !$cast(saved, stored)) `uvm_fatal("GUIDANCE", "Missing object configuration")
    $display("REVIEW|stored_clone_isolated|%0d", saved != original && saved.value == 42);
    if (!reader.get_config_object("cfg", first_object, 1) ||
        !reader.get_config_object("cfg", second_object, 1) ||
        !$cast(first, first_object) || !$cast(second, second_object))
      `uvm_fatal("GUIDANCE", "Missing consumer configuration")
    first.value = 7;
    $display("REVIEW|consumer_clones_isolated|%0d", first != second && second.value == 42 && saved.value == 42);
    uvm_config_db#(uvm_object)::set(null, "reader", "shared", original);
    original.value = 123;
    found = uvm_config_db#(uvm_object)::get(reader, "", "shared", stored);
    $display("REVIEW|direct_db_shares_handle|%0d", found && stored == original);
    partial_a.value = 1; partial_b.value = 2;
    explicit_a.value = 1; explicit_b.value = 2;
    $display("REVIEW|partial_compare|%0d", partial_a.compare(partial_b));
    $display("REVIEW|explicit_compare|%0d", explicit_a.compare(explicit_b));
    explicit_a.copy(explicit_b);
    $display("REVIEW|explicit_copy_excluded|%0d", explicit_a.value == 1);
    $display("REVIEW|done|1");
    $finish;
  end
endmodule
