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

class macro_item extends uvm_sequence_item;
  rand int value;
  `uvm_object_utils(macro_item)
  function new(string name="macro_item"); super.new(name); endfunction
endclass

class macro_sequence extends uvm_sequence#(macro_item);
  `uvm_object_utils(macro_sequence)
  function new(string name="macro_sequence"); super.new(name); endfunction
  task body();
`ifdef REVIEW_UVM20
`ifdef REVIEW_DEPRECATED
    `uvm_do_on_pri_with(req, m_sequencer, 37, { value == 42; })
`else
    `uvm_do(req, m_sequencer, 37, { value == 42; })
`endif
`else
    `uvm_do_on_pri_with(req, m_sequencer, 37, { value == 42; })
`endif
  endtask
endclass

class observing_sequencer extends uvm_sequencer#(macro_item);
  int observed_priority;
  function new(string name, uvm_component parent); super.new(name, parent); endfunction
  virtual task wait_for_grant(uvm_sequence_base sequence_ptr,
                             int item_priority = -1, bit lock_request = 0);
    observed_priority = item_priority;
    super.wait_for_grant(sequence_ptr, item_priority, lock_request);
  endtask

  // Supply a deterministic queue to the real protected lock-grant algorithm.
  function int lock_probe(bit request_first, uvm_sequence_base a, uvm_sequence_base b);
    uvm_sequence_request r;
    arb_sequence_q.delete();
    lock_list.delete();
    for (int i=0; i<2; i++) begin
      r = new();
      r.request_id = 9000+i;
      r.process_id = process::self();
      r.sequence_ptr = i == 0 ? a : b;
      r.request = request_first && i==0 ? SEQ_TYPE_REQ : SEQ_TYPE_LOCK;
      arb_sequence_q.push_back(r);
    end
    grant_queued_locks();
    lock_probe = lock_list.size();
    arb_sequence_q.delete();
    lock_list.delete();
  endfunction
endclass

module sequence_probe;
  initial begin
    macro_sequence seq_a = new("a"), seq_b = new("b");
    observing_sequencer sqr = new("sqr", null);
    macro_item received;
    int value;
    $display("REVIEW|leading_locks|%0d", sqr.lock_probe(0, seq_a, seq_b));
    $display("REVIEW|lock_after_request|%0d", sqr.lock_probe(1, seq_a, seq_b));
    seq_a.set_response_queue_error_report_disabled(1);
    $display("REVIEW|response_disabled|%0d", seq_a.get_response_queue_error_report_disabled());
    fork
      seq_a.start(sqr);
      begin
        sqr.get_next_item(received);
        value = received.value;
        sqr.item_done();
      end
    join
    $display("REVIEW|macro_constraint|%0d", value);
    $display("REVIEW|macro_priority|%0d", sqr.observed_priority);
    $display("REVIEW|macro_sequencer|%0d", received.get_sequencer() == sqr);
    $display("REVIEW|macro_parent|%0d", received.get_parent_sequence() == seq_a);
    $display("REVIEW|done|1");
    $finish;
  end
  initial begin #100; $fatal(1, "sequence probe timeout"); end
endmodule
