Tutorials
Learn More
TLM Analysis interface
TLM analysis port
- The uvm_analysis_port is a TLM-based class that provides a write method for communication. TLM analysis port broadcasts transactions to one or multiple components.
- uvm_analysis_port can be open without any implementation of uvm_analysis_imp or uvm_analysis_export.
- Single uvm_analysis_port can have a connection with uvm_analysis_imp or uvm_analysis_export. No errors will be reported.
- Multiple uvm_analysis_port can be connected to a single uvm_analysis_imp or uvm_analysis_export.
- uvm_subscriber already has analysis_export so that it can directly receive transactions from the connected analysis port. Generally, it is useful to write a coverage collector that attaches to the monitor.
- Valid Connections:
a. port to port
b. port to export
c. port to imp
d. export to export
e. export to imp
Analysis Ports Declaration:
uvm_analysis_port #(<trans_item>) analysis_port;
uvm_analysis_imp #(<trans_item>, <receiver_component>) analysis_imp;
uvm_analysis_export #(<trans_item>) analysis_export;
tlm_analysis_port example
seq_item.sv
class seq_item extends uvm_sequence_item;
rand bit [3:0] value;
`uvm_object_utils(seq_item)
function new(string name = "seq_item");
super.new(name);
endfunction
constraint val_c {value > 0;}
endclass
`include "uvm_macros.svh"
import uvm_pkg::*;
`include "seq_item.sv"
class producer extends uvm_component;
seq_item req;
uvm_analysis_port #(seq_item) a_put;
`uvm_component_utils(producer)
function new(string name = "producer", uvm_component parent = null);
super.new(name, parent);
a_put = new("a_put", this);
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
req = seq_item::type_id::create("req");
assert(req.randomize());
`uvm_info(get_type_name(), $sformatf("Send value = %0h", req.value), UVM_NONE);
a_put.write(req);
endtask
endclass
class consumer_A extends uvm_component;
seq_item req;
uvm_analysis_imp #(seq_item, consumer_A) analysis_imp_A;
`uvm_component_utils(consumer_A)
function new(string name = "consumer_A", uvm_component parent = null);
super.new(name, parent);
analysis_imp_A = new("analysis_imp_A", this);
endfunction
virtual function void write(seq_item req);
`uvm_info(get_type_name(), $sformatf("Received value = %0h", req.value), UVM_NONE);
endfunction
endclass
class consumer_B extends uvm_component;
seq_item req;
uvm_analysis_imp #(seq_item, consumer_B) analysis_imp_B;
`uvm_component_utils(consumer_B)
function new(string name = "consumer_B", uvm_component parent = null);
super.new(name, parent);
analysis_imp_B = new("analysis_imp_B", this);
endfunction
virtual function void write(seq_item req);
`uvm_info(get_type_name(), $sformatf("Received value = %0h", req.value), UVM_NONE);
endfunction
endclass
class consumer_C extends uvm_subscriber #(seq_item);
seq_item req;
`uvm_component_utils(consumer_C)
function new(string name = "consumer_C", uvm_component parent = null);
super.new(name, parent);
endfunction
virtual function void write (seq_item t);
req = t;
`uvm_info(get_type_name(), $sformatf("Received value = %0h", req.value), UVM_NONE);
endfunction
endclass
class env extends uvm_env;
producer pro;
consumer_A con_A;
consumer_B con_B;
consumer_C con_C;
`uvm_component_utils(env)
function new(string name = "env", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
pro = producer::type_id::create("pro", this);
con_A = consumer_A::type_id::create("con_A", this);
con_B = consumer_B::type_id::create("con_B", this);
con_C = consumer_C::type_id::create("con_C", this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
pro.a_put.connect(con_A.analysis_imp_A);
pro.a_put.connect(con_B.analysis_imp_B);
pro.a_put.connect(con_C.analysis_export);
endfunction
endclass
class test extends uvm_test;
env env_o;
`uvm_component_utils(test)
function new(string name = "test", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
env_o = env::type_id::create("env_o", this);
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this);
#50;
phase.drop_objection(this);
endtask
endclass
module tb_top;
initial begin
run_test("test");
end
endmodule
Output:
UVM_INFO testbench.sv(22) @ 0: uvm_test_top.env_o.pro [producer] Send value = 6
UVM_INFO testbench.sv(39) @ 0: uvm_test_top.env_o.con_A [consumer_A] Received value = 6
UVM_INFO testbench.sv(55) @ 0: uvm_test_top.env_o.con_B [consumer_B] Received value = 6
UVM_INFO testbench.sv(69) @ 0: uvm_test_top.env_o.con_C [consumer_C] Received value = 6
TLM analysis Export
- Exports lower level uvm_analysis_imp to a higher component in hierarchy.
- Lower level component implementation details will be hidden which ultimately enhances the modularity of the verification environment.
- This enables the reuse and changing of particular child components.
TLM analysis Export Example
In the below example, the consumer component is considered a child component. Consumer wrapper is a component at a higher hierarchical level.
`include "uvm_macros.svh"
import uvm_pkg::*;
`include "seq_item.sv"
class producer extends uvm_component;
seq_item req;
uvm_analysis_port #(seq_item) a_put;
`uvm_component_utils(producer)
function new(string name = "producer", uvm_component parent = null);
super.new(name, parent);
a_put = new("a_put", this);
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
req = seq_item::type_id::create("req");
assert(req.randomize());
`uvm_info(get_type_name(), $sformatf("Send value = %0h", req.value), UVM_NONE);
a_put.write(req);
endtask
endclass
class consumer extends uvm_component;
seq_item req;
uvm_analysis_imp #(seq_item, consumer) a_imp;
`uvm_component_utils(consumer)
function new(string name = "consumer", uvm_component parent = null);
super.new(name, parent);
a_imp = new("a_imp", this);
endfunction
virtual function void write(seq_item req);
`uvm_info(get_type_name(), $sformatf("Received value = %0h", req.value), UVM_NONE);
endfunction
endclass
class consumer_wrapper extends uvm_component;
seq_item req;
consumer con;
uvm_analysis_export #(seq_item) a_export;
`uvm_component_utils(consumer_wrapper)
function new(string name = "consumer_wrapper", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
a_export = new("a_export");
con = consumer::type_id::create("con", this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
a_export.connect(con.a_imp);
endfunction
endclass
class env extends uvm_env;
producer pro;
consumer_wrapper con_wrap;
`uvm_component_utils(env)
function new(string name = "env", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
pro = producer::type_id::create("pro", this);
con_wrap = consumer_wrapper::type_id::create("con_wrap", this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
pro.a_put.connect(con_wrap.a_export);
endfunction
endclass
class test extends uvm_test;
env env_o;
`uvm_component_utils(test)
function new(string name = "test", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
env_o = env::type_id::create("env_o", this);
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this);
#50;
phase.drop_objection(this);
endtask
endclass
module tb_top;
initial begin
run_test("test");
end
endmodule
Output:
UVM_INFO testbench.sv(22) @ 0: uvm_test_top.env_o.pro [producer] Send value = 5
UVM_INFO testbench.sv(39) @ 0: uvm_test_top.env_o.con_wrap.con [consumer] Received value = 5
TLM Tutorials