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

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

class event_counter extends uvm_event_callback;
  int calls;
  function new(); super.new("event_counter"); endfunction
  virtual function void post_trigger(uvm_event e, uvm_object data); calls++; endfunction
endclass

class interface_catcher extends uvm_report_catcher;
  int seen[string];
  function new(); super.new("interface_catcher"); endfunction
  function action_e catch();
    if (get_id() inside {"HIGH_WARNING", "DEMOTED_WARNING", "DIRECT_NO_ACTION"}) begin
      seen[get_id()]++;
      return CAUGHT;
    end
    return THROW;
  endfunction
endclass

class automatic_component extends uvm_component;
  int value;
  `uvm_component_utils_begin(automatic_component)
    `uvm_field_int(value, UVM_ALL_ON)
  `uvm_component_utils_end
  function new(string name, uvm_component parent); super.new(name, parent); endfunction
`ifdef REVIEW_UVM20
  virtual function bit use_automatic_config(); return !$test$plusargs("DISABLE_AUTO_CONFIG"); endfunction
`endif
endclass

class hidden_component extends uvm_component;
  `uvm_component_utils(hidden_component)
  int value;
  function new(string name, uvm_component parent); super.new(name, parent); endfunction
endclass

class interface_register extends uvm_reg;
  function new(string name="register"); super.new(name, 32, UVM_NO_COVERAGE); endfunction
endclass

class interface_block extends uvm_reg_block;
  function new(); super.new("block", UVM_NO_COVERAGE); endfunction
endclass

module interface_probe;
  initial begin
    event_counter callback = new();
    uvm_event ev = new("ev");
    interface_catcher catcher = new();
    uvm_report_object reporter = new("reporter");
    uvm_pool#(string,int) pool = new();
    uvm_queue#(int) queue_value = new();
    uvm_tlm_fifo#(int) fifo = new("fifo", null, 8);
    automatic_component automatic_value = new("automatic_value", null);
    hidden_component hidden_value = new("hidden_value", null);
    interface_block model = new();
    interface_register register_value = new();
    uvm_reg_field field_value = new("field");
    uvm_reg_map read_map, write_map;
    uvm_resource#(bit) reset_resource;
    uvm_phase run_node;
    process blocked;
    int value, regex_value;
    bit ok;
    string modes[] = '{"W1C", "WRC", "W1SRC", "W0SRC", "W1CRS", "W0CRS", "WCRS", "WSRC", "WO"};

    #1;
    $display("REVIEW|object_bare_type_name|%s", interface_object::type_name);
    $display("REVIEW|registry_bare_type_name|%s", interface_object::type_id::type_name);
    $display("REVIEW|component_bare_type_name|%s", uvm_agent::type_name);
    $display("REVIEW|event_type_name|%s", ev.get_type_name());
    $display("REVIEW|pool_type_name|%s", pool.get_type_name());
    $display("REVIEW|queue_type_name|%s", queue_value.get_type_name());
`ifdef REVIEW_UVM20
    uvm_callbacks#(uvm_event, uvm_event_callback)::add(ev, callback);
`else
    ev.add_callback(callback);
`endif
    ev.trigger();
`ifdef REVIEW_UVM20
    uvm_callbacks#(uvm_event, uvm_event_callback)::delete(ev, callback);
`else
    ev.delete_callback(callback);
`endif
    ev.trigger();
    $display("REVIEW|event_callback_calls|%0d", callback.calls);

    uvm_report_cb::add(reporter, catcher);
    reporter.set_report_verbosity_level(UVM_NONE);
    reporter.uvm_report_warning("HIGH_WARNING", "explicit verbosity", UVM_HIGH);
    reporter.set_report_severity_id_override(UVM_WARNING, "DEMOTED_WARNING", UVM_INFO);
    reporter.uvm_report_warning("DEMOTED_WARNING", "demoted verbosity", UVM_HIGH);
    reporter.set_report_id_action("DIRECT_NO_ACTION", UVM_NO_ACTION);
    reporter.uvm_report_warning("DIRECT_NO_ACTION", "direct call", UVM_NONE);
    $display("REVIEW|high_warning_seen|%0d", catcher.seen["HIGH_WARNING"]);
    $display("REVIEW|demoted_warning_seen|%0d", catcher.seen["DEMOTED_WARNING"]);
    $display("REVIEW|direct_no_action_seen|%0d", catcher.seen["DIRECT_NO_ACTION"]);

    uvm_config_db#(int)::set(null, "automatic_value", "value", 42);
    uvm_config_db#(int)::set(null, "hidden_value", "value", 42);
    automatic_value.build_phase(null);
    hidden_value.build_phase(null);
    $display("REVIEW|automatic_field|%0d", automatic_value.value);
    $display("REVIEW|unregistered_field|%0d", hidden_value.value);
    uvm_config_db#(int)::set(automatic_value, "/agent(0|1)/", "regex", 51);
    ok = uvm_config_db#(int)::get(null, "automatic_value.agent1", "regex", regex_value);
    $display("REVIEW|relative_regex|%0d:%0d", ok, regex_value);

    register_value.configure(model);
    field_value.configure(register_value, 32, 0, "RW", 0, 0, 0, 1, 1);
    read_map = model.create_map("read_map", 0, 4, UVM_LITTLE_ENDIAN);
    write_map = model.create_map("write_map", 0, 4, UVM_LITTLE_ENDIAN);
    read_map.add_reg(register_value, 0, "RO");
    write_map.add_reg(register_value, 0, "WO");
    model.lock_model();
    reset_resource = uvm_resource_db#(bit)::get_by_name({"REG::", field_value.get_full_name()}, "NO_REG_HW_RESET_TEST", 0);
    $display("REVIEW|automatic_reset_resource|%0d", reset_resource != null);
    foreach (modes[i]) begin
      void'(field_value.set_access(modes[i]));
      $display("REVIEW|access_%s|%s:%s", modes[i], field_value.get_access(read_map), field_value.get_access(write_map));
    end

    fork
      begin
        blocked = process::self();
        fifo.get(value);
      end
    join_none
    #1;
    blocked.kill();
    ok = fifo.try_put(19);
    $display("REVIEW|fifo_after_kill_can_get|%0d", fifo.can_get());
    $display("REVIEW|fifo_after_kill_used|%0d", fifo.used());
    $display("REVIEW|done|1");
    $finish;
  end
endmodule
