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

class payload_target extends uvm_component;
  uvm_tlm_b_target_socket#(payload_target) socket;
  int calls;
  function new(string name, uvm_component parent);
    super.new(name, parent);
    socket = new("socket", this, this);
  endfunction
  virtual task b_transport(uvm_tlm_generic_payload tx, uvm_tlm_time delay);
    calls++;
    if (tx.get_command() == UVM_TLM_WRITE_COMMAND && tx.get_address() == 'h20)
      tx.set_response_status(UVM_TLM_OK_RESPONSE);
    else tx.set_response_status(UVM_TLM_ADDRESS_ERROR_RESPONSE);
  endtask
endclass

class socket_test extends uvm_test;
  `uvm_component_utils(socket_test)
  uvm_tlm_b_initiator_socket#() socket;
  payload_target target;
  function new(string name, uvm_component parent); super.new(name, parent); endfunction
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    socket = new("socket", this);
    target = new("target", this);
  endfunction
  function void connect_phase(uvm_phase phase);
    socket.connect(target.socket);
  endfunction
  task run_phase(uvm_phase phase);
    uvm_tlm_generic_payload tx = new("tx");
    uvm_tlm_time delay = new("delay");
    phase.raise_objection(this);
    tx.set_command(UVM_TLM_WRITE_COMMAND);
    tx.set_address('h20);
    socket.b_transport(tx, delay);
    $display("REVIEW|response_ok|%0d", tx.get_response_status() == UVM_TLM_OK_RESPONSE);
    tx.set_address('h24);
    socket.b_transport(tx, delay);
    $display("REVIEW|bad_address_rejected|%0d", tx.get_response_status() == UVM_TLM_ADDRESS_ERROR_RESPONSE);
    $display("REVIEW|target_calls|%0d", target.calls);
    $display("REVIEW|done|1");
    phase.drop_objection(this);
  endtask
endclass

module socket_migration_probe;
  initial run_test("socket_test");
endmodule
