uvm-tlm-port-export-imp
UVM TLM端口和导出也用于跨测试平台层次结构的不同层级发送事务对象。
端口应用于发起并将数据包转发至层次结构的顶层。导出则用于接收并将数据包从顶层转发至目标位置。实现端口用于在目标位置定义put方法。以下示例展示了针对不同层级组件使用端口、导出及实现的具体案例。
Port to Port to Export to Imp
subCompA是componentA中的一个子组件,它试图向componentB中名为subCompB的另一个子组件发送交易。为了保持代码的灵活性和可移植性,建议允许subCompA将数据发送到componentA,然后由componentA将其转发到层级结构的顶层。componentB应接收该交易并将其转发给subCompB。
下面定义了一个名为Packet
的类,作为将在不同组件之间传输的数据项。该类的对象将包含两个可以在发送前随机化的随机变量。
// Create a class data object that can be sent from one
// component to another
class Packet extends uvm_object;rand bit[7:0] addr;rand bit[7:0] data;`uvm_object_utils_begin(Packet)`uvm_field_int(addr, UVM_ALL_ON)`uvm_field_int(data, UVM_ALL_ON)`uvm_object_utils_endfunction new(string name = "Packet");super.new(name);endfunction
endclass
Subcomponent A
class subCompA extends uvm_component;`uvm_component_utils (subCompA)function new(string name, uvm_component parent);super.new(name, parent);endfunctionuvm_blocking_put_port #(Packet) m_put_port;int m_num_tx=2;virtual function void build_phase(uvm_phase phase);super.build_phase(phase);m_put_port = new ("m_put_port", this);endfunction// Create a packet, randomize it and send it through the port// Note that put() is a method defined by the receiving component// Repeat these steps N times to send N packetsvirtual task run_phase (uvm_phase phase);phase.raise_objection(this);repeat (m_num_tx) beginPacket pkt = Packet::type_id::create ("pkt");assert(pkt.randomize ());// Print the packet to be displayed in log`uvm_info ("SUBCOMPA", "Packet sent to subCompB", UVM_LOW)pkt.print (uvm_default_line_printer);// Call the TLM put() method of put_port class and pass packet as argumentm_put_port.put (pkt);endphase.drop_objection(this);endtask
endclass
Component A
class componentA extends uvm_component;`uvm_component_utils (componentA)function new (string name = "componentA", uvm_component parent= null);super.new (name, parent);endfunctionsubCompA m_subcomp_A;uvm_blocking_put_port #(Packet) m_put_port;virtual function void build_phase(uvm_phase phase);super.build_phase(phase);m_subcomp_A = subCompA::type_id::create("m_subcomp_A", this);m_put_port = new ("m_put_port", this);endfunction// Connection with subCompAvirtual function void connect_phase(uvm_phase phase);super.connect_phase(phase);m_subcomp_A.m_put_port.connect(this.m_put_port);endfunction
endclass
Component B
class componentB extends uvm_component;`uvm_component_utils (componentB)function new(string name, uvm_component parent);super.new(name, parent);endfunctionsubCompB m_subcomp_B;uvm_blocking_put_export#(Packet) m_put_export;virtual function void build_phase(uvm_phase phase);super.build_phase(phase);m_subcomp_B = subCompB::type_id::create("m_subcomp_B", this);m_put_export = new("m_put_export", this);endfunction// Connection with subCompBvirtual function void connect_phase(uvm_phase phase);m_put_export.connect(m_subcomp_B.m_put_imp);endfunction
endclass
Subcomponent B
class subCompB extends uvm_component;`uvm_component_utils (subCompB)function new (string name = "subCompB", uvm_component parent = null);super.new (name, parent);endfunction// Mention type of transaction, and type of class that implements the put ()uvm_blocking_put_imp #(Packet, subCompB) m_put_imp;virtual function void build_phase (uvm_phase phase);super.build_phase (phase);m_put_imp = new ("m_put_imp", this);endfunction// Implementation of the 'put()' method in this case simply prints it.virtual task put (Packet pkt);`uvm_info ("SUBCOMPB", "Packet received from subCompA", UVM_LOW)pkt.print(uvm_default_line_printer);endtask
endclass
class my_test extends uvm_test;`uvm_component_utils (my_test)componentA compA;componentB compB;function new (string name = "my_test", uvm_component parent = null);super.new (name, parent);endfunction// Create objects of both components, set number of transfersvirtual function void build_phase (uvm_phase phase);super.build_phase (phase);compA = componentA::type_id::create ("compA", this);compB = componentB::type_id::create ("compB", this);endfunction// Connection between componentA and componentB is done herevirtual function void connect_phase (uvm_phase phase);compA.m_put_port.connect (compB.m_put_export);endfunctionvirtual function void end_of_elaboration_phase(uvm_phase phase);super.end_of_elaboration_phase(phase);uvm_top.print_topology();endfunction
endclass
Simulation Log
UVM_INFO @ 0: reporter [RNTST] Running test my_test...
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_root.svh(579) @ 0: reporter [UVMTOP] UVM testbench topology:
------------------------------------------------------
Name Type Size Value
------------------------------------------------------
uvm_test_top my_test - @1842compA componentA - @1911m_put_port uvm_blocking_put_port - @2008m_subcomp_A subCompA - @1974m_put_port uvm_blocking_put_port - @2047compB componentB - @1942m_put_export uvm_blocking_put_export - @2115m_subcomp_B subCompB - @2081m_put_imp uvm_blocking_put_imp - @2152
------------------------------------------------------UVM_INFO testbench.sv(71) @ 0: uvm_test_top.compA.m_subcomp_A [SUBCOMPA] Packet sent to subCompB
pkt: (Packet@2191) { addr: 'h24 data: 'h31 }
UVM_INFO testbench.sv(151) @ 0: uvm_test_top.compB.m_subcomp_B [SUBCOMPB] Packet received from subCompA
pkt: (Packet@2191) { addr: 'h24 data: 'h31 }
UVM_INFO testbench.sv(71) @ 0: uvm_test_top.compA.m_subcomp_A [SUBCOMPA] Packet sent to subCompB
pkt: (Packet@2209) { addr: 'h9a data: 'hfb }
UVM_INFO testbench.sv(151) @ 0: uvm_test_top.compB.m_subcomp_B [SUBCOMPB] Packet received from subCompA
pkt: (Packet@2209) { addr: 'h9a data: 'hfb }
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_objection.svh(1271) @ 0: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 0: reporter [UVM/REPORT/SERVER]
--- UVM Report Summary ---
Port to Port to Imp
在本示例中,组件A将数据包从子组件A转发至目标组件B。唯一区别在于组件B作为接收方,应定义实现端口而非导出端口。
// componentB shall implement "put" and there's no subCompB
class componentB extends uvm_component;`uvm_component_utils (componentB)function new(string name, uvm_component parent);super.new(name, parent);endfunctionuvm_blocking_put_imp#(Packet, componentB) m_put_imp;virtual function void build_phase(uvm_phase phase);super.build_phase(phase);m_put_imp = new("m_put_imp", this);endfunction// Implementation of the 'put()' method in this case simply prints it.virtual task put (Packet pkt);`uvm_info ("COMPB", "Packet received from subCompA", UVM_LOW)pkt.print(uvm_default_line_printer);endtask
endclass
Simulation Log
UVM_INFO @ 0: reporter [RNTST] Running test my_test...
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_root.svh(579) @ 0: reporter [UVMTOP] UVM testbench topology:
----------------------------------------------------
Name Type Size Value
----------------------------------------------------
uvm_test_top my_test - @1839compA componentA - @1908m_put_port uvm_blocking_put_port - @2005m_subcomp_A subCompA - @1971m_put_port uvm_blocking_put_port - @2044compB componentB - @1939m_put_imp uvm_blocking_put_imp - @2081
----------------------------------------------------UVM_INFO testbench.sv(70) @ 0: uvm_test_top.compA.m_subcomp_A [SUBCOMPA] Packet sent to CompB
pkt: (Packet@2119) { addr: 'h24 data: 'h31 }
UVM_INFO testbench.sv(124) @ 0: uvm_test_top.compB [COMPB] Packet received from subCompA
pkt: (Packet@2119) { addr: 'h24 data: 'h31 }
UVM_INFO testbench.sv(70) @ 0: uvm_test_top.compA.m_subcomp_A [SUBCOMPA] Packet sent to CompB
pkt: (Packet@2133) { addr: 'h9a data: 'hfb }
UVM_INFO testbench.sv(124) @ 0: uvm_test_top.compB [COMPB] Packet received from subCompA
pkt: (Packet@2133) { addr: 'h9a data: 'hfb }
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_objection.svh(1271) @ 0: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 0: reporter [UVM/REPORT/SERVER]
--- UVM Report Summary ---
Port to Export to Imp
在本示例中,组件A将数据包从子组件A转发至目标组件B。唯一区别在于组件B作为接收方,应定义实现端口而非导出端口。
// componentA will start transactions and send to its port
class componentA extends uvm_component;`uvm_component_utils (componentA)function new (string name = "componentA", uvm_component parent= null);super.new (name, parent);endfunctionuvm_blocking_put_port #(Packet) m_put_port;int m_num_tx=2;virtual function void build_phase(uvm_phase phase);super.build_phase(phase);m_put_port = new ("m_put_port", this);endfunction// Create a packet, randomize it and send it through the port// Note that put() is a method defined by the receiving component// Repeat these steps N times to send N packetsvirtual task run_phase (uvm_phase phase);phase.raise_objection(this);repeat (m_num_tx) beginPacket pkt = Packet::type_id::create ("pkt");assert(pkt.randomize ());// Print the packet to be displayed in log`uvm_info ("SUBCOMPA", "Packet sent to subCompB", UVM_LOW)pkt.print (uvm_default_line_printer);// Call the TLM put() method of put_port class and pass packet as argumentm_put_port.put (pkt);endphase.drop_objection(this);endtask
endclass
Simulation Log
UVM_INFO @ 0: reporter [RNTST] Running test my_test...
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_root.svh(579) @ 0: reporter [UVMTOP] UVM testbench topology:
------------------------------------------------------
Name Type Size Value
------------------------------------------------------
uvm_test_top my_test - @1839compA componentA - @1908m_put_port uvm_blocking_put_port - @1974compB componentB - @1939m_put_export uvm_blocking_put_export - @2044m_subcomp_B subCompB - @2010m_put_imp uvm_blocking_put_imp - @2081
------------------------------------------------------UVM_INFO testbench.sv(73) @ 0: uvm_test_top.compA [SUBCOMPA] Packet sent to subCompB
pkt: (Packet@2120) { addr: 'ha1 data: 'h64 }
UVM_INFO testbench.sv(127) @ 0: uvm_test_top.compB.m_subcomp_B [SUBCOMPB] Packet received from subCompA
pkt: (Packet@2120) { addr: 'ha1 data: 'h64 }
UVM_INFO testbench.sv(73) @ 0: uvm_test_top.compA [SUBCOMPA] Packet sent to subCompB
pkt: (Packet@2134) { addr: 'hc1 data: 'hb9 }
UVM_INFO testbench.sv(127) @ 0: uvm_test_top.compB.m_subcomp_B [SUBCOMPB] Packet received from subCompA
pkt: (Packet@2134) { addr: 'hc1 data: 'hb9 }
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_objection.svh(1271) @ 0: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 0: reporter [UVM/REPORT/SERVER]
--- UVM Report Summary ---
Port to Port to Export to Export to Imp
在此示例中,componentB
和目标 subCompB2
之间存在一个名为 subCompB1
的附加层。该层只需将数据包转发到目的地,因此应包含一个 export
。
Simulation Log
UVM_INFO @ 0: reporter [RNTST] Running test my_test...
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_root.svh(579) @ 0: reporter [UVMTOP] UVM testbench topology:
--------------------------------------------------------
Name Type Size Value
--------------------------------------------------------
uvm_test_top my_test - @1845compA componentA - @1914m_put_port uvm_blocking_put_port - @2011m_subcomp_A subCompA - @1977m_put_port uvm_blocking_put_port - @2050compB componentB - @1945m_put_export uvm_blocking_put_export - @2118m_subcomp_B1 subCompB1 - @2084m_put_export uvm_blocking_put_export - @2186m_subcomp_B2 subCompB2 - @2152m_put_imp uvm_blocking_put_imp - @2223
--------------------------------------------------------UVM_INFO testbench.sv(75) @ 0: uvm_test_top.compA.m_subcomp_A [SUBCOMPA] Packet sent to subCompB
pkt: (Packet@2262) { addr: 'h24 data: 'h31 }
UVM_INFO testbench.sv(179) @ 0: uvm_test_top.compB.m_subcomp_B1.m_subcomp_B2 [SUBCOMPB2] Packet received from subCompA
pkt: (Packet@2262) { addr: 'h24 data: 'h31 }
UVM_INFO testbench.sv(75) @ 0: uvm_test_top.compA.m_subcomp_A [SUBCOMPA] Packet sent to subCompB
pkt: (Packet@2284) { addr: 'h9a data: 'hfb }
UVM_INFO testbench.sv(179) @ 0: uvm_test_top.compB.m_subcomp_B1.m_subcomp_B2 [SUBCOMPB2] Packet received from subCompA
pkt: (Packet@2284) { addr: 'h9a data: 'hfb }
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_objection.svh(1271) @ 0: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 0: reporter [UVM/REPORT/SERVER]
--- UVM Report Summary ---