The put/get communication we have seen earlier typically require a corresponding export to supply the implementation. The idea behind having an analysis port is that a component like monitor should be able to generate a stream of transactions regardless of whether there is a target actually connected to it.
The uvm_analysis_port
is a specialized TLM based class whose interface consists of a single function write ()
and can be embedded within any component as shown in the snippet below. This port contains a list of analysis exports that are connected to it. When the component (my_monitor) calls analysis_port.write()
, it basically cycles through the list and calls the write()
method of each connected export. If nothing is connected to it, then it simply does not do anything.
class my_monitor extends uvm_component;
...
uvm_analysis_port #(my_data) analysis_port;
...
endclass
The advantage lies in the fact that an analysis port may be connected to zero, one or many analysis exports and allows a component to call write()
method without depending on the number of connected exports. Also it's worth to note that write()
is a void function and hence will always complete within the same simulation delta cycle.
Example

Let's take component B from the TLM Put example and connect three Subscribers to it. In order for component B to broadcast transactions to it's subscribers, there needs to be a special channel for communication. This is implemented by analysis ports. Analysis ports are declared using uvm_analysis_port
so that component B can send transactions into the channel. We'll see how we can connect subscribers to this channel in a short while.
Declare analysis port
class componentB extends uvm_component;
`uvm_component_utils (componentB)
// Create an analysis port by the name "ap" that can broadcast packets of type "simple_packet"
uvm_analysis_port #(simple_packet) ap;
function new (string name = "componentB", uvm_component parent = null);
super.new (name, parent);
endfunction
virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
ap = new ("analysis_port", this);
endfunction
virtual task run_phase (uvm_phase phase);
super.run_phase (phase);
for (int i = 0; i < 5; i++) begin
simple_packet pkt = simple_packet::type_id::create ("pkt");
pkt.randomize();
// Now pass it to other components via the analysis port write() method
ap.write (pkt);
end
endtask
endclass
Define analysis port implementation
Now let us create the subscriber component parameterized to simple_packet data type. Note that the subscriber implements the write()
method, and for our purpose, we can just display a message. Because we have derived our subscriber from uvm_subscriber
, it already has an analysis port implementation object predefined by the name analysis_export. Hence we won't have to declare another implementation port for our purpose. See the snippet of uvm_subscriber
class below.
virtual class uvm_subscriber #(type T=int) extends uvm_component;
typedef uvm_subscriber #(T) this_type;
uvm_analysis_imp #(T, this_type) analysis_export;
pure virtual function void write (T t);
endclass
Note that analysis ports given by uvm_analysis_port
are always connected to its implementation port declared using uvm_analysis_imp
. Function write()
is the place where you need to implement the operation required to be done on the incoming transaction. In this example, we are simply printing an acknowledgment statment.
class sub #(type T = simple_packet) extends uvm_subscriber #(T);
`uvm_component_utils (sub)
function new (string name = "sub", uvm_component parent = null);
super.new (name, parent);
endfunction
virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
endfunction
// Note that the class object name has to be "t" - anything else will result
// in compilation error
virtual function void write (T t);
`uvm_info (get_full_name(), "Sub got transaction", UVM_MEDIUM)
endfunction
endclass

Connect analysis port with its implementation
Since all our components are instantiated within the environment my_env, it is easier to connect between components at this level. This is done in the connect_phase()
method where the analysis port of component B is connected with multiple implementation ports defined within each subscriber.
class my_env extends uvm_env;
`uvm_component_utils (my_env)
componentA compA;
componentB compB;
sub sub1;
sub sub2;
sub sub3;
function new (string name = "my_env", uvm_component parent = null);
super.new (name, parent);
endfunction
virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
// Create an object of both components
compA = componentA::type_id::create ("compA", this);
compB = componentB::type_id::create ("compB", this);
sub1 = sub::type_id::create ("sub1", this);
sub2 = sub::type_id::create ("sub2", this);
sub3 = sub::type_id::create ("sub3", this);
endfunction
virtual function void connect_phase (uvm_phase phase);
compA.put_port.connect (compB.put_export);
// Connect Analysis Ports
compB.ap.connect (sub1.analysis_export);
compB.ap.connect (sub2.analysis_export);
compB.ap.connect (sub3.analysis_export);
endfunction
endclass
---------------------------------------------------------------- CDNS-UVM-1.1d (15.10-s004) (C) 2007-2013 Mentor Graphics Corporation (C) 2007-2013 Cadence Design Systems, Inc. (C) 2006-2013 Synopsys, Inc. (C) 2011-2013 Cypress Semiconductor Corp. ---------------------------------------------------------------- UVM_INFO @ 0: reporter [RNTST] Running test base_test... UVM_INFO @ 0: reporter [UVMTOP] UVM testbench topology: ------------------------------------------------------- Name Type Size Value ------------------------------------------------------- uvm_test_top base_test - @2602 m_top_env my_env - @2668 compA componentA - @2699 put_port uvm_blocking_put_port - @3015 compB componentB - @2729 analysis_port uvm_analysis_port - @3115 put_export uvm_blocking_put_imp - @3066 sub1 sub - @2759 analysis_imp uvm_analysis_imp - @2808 sub2 sub - @2839 analysis_imp uvm_analysis_imp - @2888 sub3 sub - @2869 analysis_imp uvm_analysis_imp - @2966 ------------------------------------------------------- UVM_INFO ./tb/tlm.sv(61) @ 0: uvm_test_top.m_top_env.compA [COMPA] Packet sent to CompB pkt: (simple_packet@3205) { addr: 'h2f data: 'h64 rwb: 'h0 } UVM_INFO ./tb/tlm.sv(91) @ 0: uvm_test_top.m_top_env.compB [COMPB] Packet received from CompA ---------------------------------- Name Type Size Value ---------------------------------- pkt simple_packet - @3205 addr integral 8 'h2f data integral 8 'h64 rwb integral 1 'h0 ---------------------------------- UVM_INFO ./tb/tlm.sv(122) @ 0: uvm_test_top.m_top_env.sub1 [uvm_test_top.m_top_env.sub1] Sub got transaction UVM_INFO ./tb/tlm.sv(122) @ 0: uvm_test_top.m_top_env.sub2 [uvm_test_top.m_top_env.sub2] Sub got transaction UVM_INFO ./tb/tlm.sv(122) @ 0: uvm_test_top.m_top_env.sub3 [uvm_test_top.m_top_env.sub3] Sub got transaction UVM_INFO ./tb/tlm.sv(61) @ 0: uvm_test_top.m_top_env.compA [COMPA] Packet sent to CompB pkt: (simple_packet@3198) { addr: 'hb8 data: 'h27 rwb: 'h0 } UVM_INFO ./tb/tlm.sv(91) @ 0: uvm_test_top.m_top_env.compB [COMPB] Packet received from CompA ---------------------------------- Name Type Size Value ---------------------------------- pkt simple_packet - @3198 addr integral 8 'hb8 data integral 8 'h27 rwb integral 1 'h0 ---------------------------------- UVM_INFO ./tb/tlm.sv(122) @ 0: uvm_test_top.m_top_env.sub1 [uvm_test_top.m_top_env.sub1] Sub got transaction UVM_INFO ./tb/tlm.sv(122) @ 0: uvm_test_top.m_top_env.sub2 [uvm_test_top.m_top_env.sub2] Sub got transaction UVM_INFO ./tb/tlm.sv(122) @ 0: uvm_test_top.m_top_env.sub3 [uvm_test_top.m_top_env.sub3] Sub got transaction UVM_INFO ./tb/tlm.sv(61) @ 0: uvm_test_top.m_top_env.compA [COMPA] Packet sent to CompB pkt: (simple_packet@3170) { addr: 'he3 data: 'h29 rwb: 'h0 } UVM_INFO ./tb/tlm.sv(91) @ 0: uvm_test_top.m_top_env.compB [COMPB] Packet received from CompA ---------------------------------- Name Type Size Value ---------------------------------- pkt simple_packet - @3170 addr integral 8 'he3 data integral 8 'h29 rwb integral 1 'h0 ---------------------------------- UVM_INFO ./tb/tlm.sv(122) @ 0: uvm_test_top.m_top_env.sub1 [uvm_test_top.m_top_env.sub1] Sub got transaction UVM_INFO ./tb/tlm.sv(122) @ 0: uvm_test_top.m_top_env.sub2 [uvm_test_top.m_top_env.sub2] Sub got transaction UVM_INFO ./tb/tlm.sv(122) @ 0: uvm_test_top.m_top_env.sub3 [uvm_test_top.m_top_env.sub3] Sub got transaction UVM_INFO ./tb/tlm.sv(61) @ 0: uvm_test_top.m_top_env.compA [COMPA] Packet sent to CompB pkt: (simple_packet@3175) { addr: 'h85 data: 'hbd rwb: 'h0 } UVM_INFO ./tb/tlm.sv(91) @ 0: uvm_test_top.m_top_env.compB [COMPB] Packet received from CompA ---------------------------------- Name Type Size Value ---------------------------------- pkt simple_packet - @3175 addr integral 8 'h85 data integral 8 'hbd rwb integral 1 'h0 ---------------------------------- UVM_INFO ./tb/tlm.sv(122) @ 0: uvm_test_top.m_top_env.sub1 [uvm_test_top.m_top_env.sub1] Sub got transaction UVM_INFO ./tb/tlm.sv(122) @ 0: uvm_test_top.m_top_env.sub2 [uvm_test_top.m_top_env.sub2] Sub got transaction UVM_INFO ./tb/tlm.sv(122) @ 0: uvm_test_top.m_top_env.sub3 [uvm_test_top.m_top_env.sub3] Sub got transaction UVM_INFO ./tb/tlm.sv(61) @ 0: uvm_test_top.m_top_env.compA [COMPA] Packet sent to CompB pkt: (simple_packet@3192) { addr: 'hdf data: 'hab rwb: 'h0 } UVM_INFO ./tb/tlm.sv(91) @ 0: uvm_test_top.m_top_env.compB [COMPB] Packet received from CompA ---------------------------------- Name Type Size Value ---------------------------------- pkt simple_packet - @3192 addr integral 8 'hdf data integral 8 'hab rwb integral 1 'h0 ---------------------------------- UVM_INFO ./tb/tlm.sv(122) @ 0: uvm_test_top.m_top_env.sub1 [uvm_test_top.m_top_env.sub1] Sub got transaction UVM_INFO ./tb/tlm.sv(122) @ 0: uvm_test_top.m_top_env.sub2 [uvm_test_top.m_top_env.sub2] Sub got transaction UVM_INFO ./tb/tlm.sv(122) @ 0: uvm_test_top.m_top_env.sub3 [uvm_test_top.m_top_env.sub3] Sub got transaction --- UVM Report catcher Summary --- Number of demoted UVM_FATAL reports : 0 Number of demoted UVM_ERROR reports : 0 Number of demoted UVM_WARNING reports: 0 Number of caught UVM_FATAL reports : 0 Number of caught UVM_ERROR reports : 0 Number of caught UVM_WARNING reports : 0 --- UVM Report Summary --- ** Report counts by severity UVM_INFO : 27 UVM_WARNING : 0 UVM_ERROR : 0 UVM_FATAL : 0 ** Report counts by id [COMPA] 5 [COMPB] 5 [RNTST] 1 [UVMTOP] 1 [uvm_test_top.m_top_env.sub1] 5 [uvm_test_top.m_top_env.sub2] 5 [uvm_test_top.m_top_env.sub3] 5 Simulation complete via $finish(1) at time 0 FS + 179