In reply to Reuben:
As Chuck said, you can look at the source code. Here it is:
class uvm_in_order_comparator
#( type T = int ,
type comp_type = uvm_built_in_comp #( T ) ,
type convert = uvm_built_in_converter #( T ) ,
type pair_type = uvm_built_in_pair #( T ) )
extends uvm_component;
typedef uvm_in_order_comparator #(T,comp_type,convert,pair_type) this_type;
`uvm_component_param_utils(this_type)
const static string type_name =
"uvm_in_order_comparator #(T,comp_type,convert,pair_type)";
// Port: before_export
//
// The export to which one stream of data is written. The port must be
// connected to an analysis port that will provide such data.
uvm_analysis_export #(T) before_export;
// Port: after_export
//
// The export to which the other stream of data is written. The port must be
// connected to an analysis port that will provide such data.
uvm_analysis_export #(T) after_export;
// Port: pair_ap
//
// The comparator sends out pairs of transactions across this analysis port.
// Both matched and unmatched pairs are published via a pair_type objects.
// Any connected analysis export(s) will receive these transaction pairs.
uvm_analysis_port #(pair_type) pair_ap;
local uvm_tlm_analysis_fifo #(T) m_before_fifo;
local uvm_tlm_analysis_fifo #(T) m_after_fifo;
int m_matches, m_mismatches;
function new(string name, uvm_component parent);
super.new(name, parent);
before_export = new("before_export", this);
after_export = new("after_export", this);
pair_ap = new("pair_ap", this);
m_before_fifo = new("before", this);
m_after_fifo = new("after", this);
m_matches = 0;
m_mismatches = 0;
endfunction
virtual function string get_type_name();
return type_name;
endfunction
virtual function void connect_phase(uvm_phase phase);
before_export.connect(m_before_fifo.analysis_export);
after_export.connect(m_after_fifo.analysis_export);
endfunction
// Task- run_phase
//
// Internal method.
//
// Takes pairs of before and after transactions and compares them.
// Status information is updated according to the results of the comparison.
// Each pair is published to the pair_ap analysis port.
virtual task run_phase(uvm_phase phase);
pair_type pair;
T b;
T a;
string s;
super.run_phase(phase);
forever begin
m_before_fifo.get(b);
m_after_fifo.get(a);
if(!comp_type::comp(b, a)) begin
$sformat(s, "%s differs from %s", convert::convert2string(a),
convert::convert2string(b));
uvm_report_warning("Comparator Mismatch", s);
m_mismatches++;
end
else begin
s = convert::convert2string(b);
uvm_report_info("Comparator Match", s);
m_matches++;
end
// we make the assumption here that a transaction "sent for
// analysis" is safe from being edited by another process.
// Hence, it is safe not to clone a and b.
pair = new("after/before");
pair.first = a;
pair.second = b;
pair_ap.write(pair);
end
endtask
// Function: flush
//
// This method sets m_matches and m_mismatches back to zero. The
// <uvm_tlm_fifo::flush> takes care of flushing the FIFOs.
virtual function void flush();
m_matches = 0;
m_mismatches = 0;
endfunction
endclass
You can see that the pair of get() calls at the beginning of the forever loop require that a matching number of transactions arrive on each export before the comparison happens. Therefore, if you get 4 of one and 3 of the other, you’ll be stuck waiting for the fourth transaction. In your test’s check_phase(), you can see if the fifos are empty. If not, then you have a mismatch in the number of transactions.