云计算百科
云计算领域专业知识百科平台

uvm-tlm-example

此UVM TLM示例运用了前文讨论的put端口、TLM FIFO和get端口,构建了一个在不同层级包含TLM端口的测试平台。

tlm-hier

TLM  FIFO 可以扩展为包含另一个名为componentB的组件,该组件使用另一个内部FIFO和子组件来接收数据包。

下面定义了一个名为Packet的类,作为在不同组件之间传输的数据项。该类的对象将包含两个随机变量,这些变量在发送前可以被随机化。

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_end

function new(string name = "Packet");
super.new(name);
endfunction
endclass

subComp1

该组件与UVM TLM FIFO示例中的完全相同,并通过其uvm_blocking_put_port开始发送数据包。

class subComp1 extends uvm_component;
`uvm_component_utils (subComp1)

// Create a blocking TLM put port which can send an object
// of type 'Packet'
uvm_blocking_put_port #(Packet) m_put_port;
int m_num_tx;

function new (string name = "subComp1", uvm_component parent= null);
super.new (name, parent);
endfunction

// Remember that TLM put_port is a class object and it will have to be
// created with new ()
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 packets
virtual task run_phase (uvm_phase phase);
repeat (m_num_tx) begin
Packet pkt = Packet::type_id::create ("pkt");
assert(pkt.randomize ());
#50;
// Print the packet to be displayed in log
`uvm_info ("SUBCOMP1", "Packet sent to compA:tlm_fifo", UVM_LOW)
pkt.print (uvm_default_line_printer);

// Call the TLM put() method of put_port class and pass packet as argument
m_put_port.put (pkt);
end
endtask
endclass

subComp2

该子组件接收数据包的速度比上文提到的组件稍慢,并通过uvm_blocking_get_port接口接收数据。

需注意:该组件还配有类型为uvm_blocking_put_port的另一个输出端口,用于从componentA向外传输数据。

class subComp2 extends uvm_component;
`uvm_component_utils (subComp2)

// Create a get_port to request for data from subComp1
uvm_blocking_get_port #(Packet) m_get_port;
uvm_blocking_put_port #(Packet) m_put_port;

function new (string name, uvm_component parent);
super.new (name, parent);
endfunction

virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
m_get_port = new ("m_get_port", this);
m_put_port = new ("m_put_port", this);
endfunction

virtual task run_phase (uvm_phase phase);
Packet pkt;
forever begin
#100;
m_get_port.get (pkt);
`uvm_info ("SUBCOMP2", "Packet received from compA:tlm_fifo, forward it", UVM_LOW)
pkt.print (uvm_default_line_printer);
m_put_port.put(pkt);
end
endtask
endclass

ComponentA

该层包含通过TLM FIFO连接的两个子组件,因为它们的传输速率不同。

请注意,它还具有另一个类型为uvm_blocking_put_port的put端口,用于转发从较低层subComp2接收的数据包。

class componentA extends uvm_component;
`uvm_component_utils (componentA)
function new(string name="componentA", uvm_component parent=null);
super.new(name, parent);
endfunction

subComp1 m_subcomp_1;
subComp2 m_subcomp_2;

uvm_tlm_fifo #(Packet) m_tlm_fifo;
uvm_blocking_put_port #(Packet) m_put_port;
int m_num_tx;

virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
// Create an object of both components
m_subcomp_1 = subComp1::type_id::create ("m_subcomp_1", this);
m_subcomp_2 = subComp2::type_id::create ("m_subcomp_2", this);

// Create a FIFO with depth 2
m_tlm_fifo = new ("uvm_tlm_fifo", this, 2);
m_put_port = new ("m_put_port", this);
m_subcomp_1.m_num_tx = m_num_tx;
endfunction

// Make componentA connections
virtual function void connect_phase (uvm_phase phase);
// Connect put port from subComp1 to TLM FIFO and then
// connect get_export of TLM FIFO with subComp2
m_subcomp_1.m_put_port.connect(m_tlm_fifo.put_export);
m_subcomp_2.m_get_port.connect(m_tlm_fifo.get_export);

// Now connect subComp2 to componentA for forwarding pkt
m_subcomp_2.m_put_port.connect(this.m_put_port);
endfunction

// Display a message when the FIFO is full
virtual task run_phase (uvm_phase phase);
forever begin
#10 if (m_tlm_fifo.is_full ())
`uvm_info ("COMPA", "componentA:TLM_Fifo is now FULL !", UVM_MEDIUM)
end
endtask
endclass

subComp3

假设目标组件比上述其他组件更慢,并且使用 uvm_blocking_get_port 来接收数据包。

// subComp3 accepts packet even slower than what componentA is sending out
// which is the reason we need a TLM FIFO in componentB
class subComp3 extends uvm_component;
`uvm_component_utils (subComp3)

// Create a get_port to request for data from subComp1
uvm_blocking_get_port #(Packet) m_get_port;
int m_num_tx;

function new (string name, uvm_component parent);
super.new (name, parent);
endfunction

virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
m_get_port = new ("m_get_port", this);
endfunction

virtual task run_phase (uvm_phase phase);
Packet pkt;
repeat(m_num_tx) begin
#200;
m_get_port.get (pkt);
`uvm_info ("SUBCOMP3", "Packet received from componentA", UVM_LOW)
pkt.print (uvm_default_line_printer);
end
endtask
endclass

ComponentB

由于目标速率较慢,需要再连接一个UVM TLM FIFO到subComp3,用于缓冲其接收的数据包。请注意,该FIFO具有一个顶层put_export端口,类型为uvm_blocking_put_export。

class componentB extends uvm_component;
`uvm_component_utils (componentB)

subComp3 m_subcomp_3;
uvm_tlm_fifo #(Packet) m_tlm_fifo;
uvm_blocking_put_export #(Packet) m_put_export;
int m_num_tx;

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);
// Create an object of both components
m_subcomp_3 = subComp3::type_id::create ("m_subcomp_3", this);

// Create a FIFO with depth 2
m_tlm_fifo = new ("tlm_fifo", this, 2);

// Create the export to connect with componentA
m_put_export = new ("m_put_export", this);

m_subcomp_3.m_num_tx = m_num_tx;
endfunction

virtual function void connect_phase (uvm_phase phase);
// Connect from componentB export to FIFO export
m_put_export.connect (m_tlm_fifo.put_export);

// Connect from FIFO export to subComponent3 port
m_subcomp_3.m_get_port.connect (m_tlm_fifo.get_export);
endfunction

// Display a message when the FIFO is full
virtual task run_phase (uvm_phase phase);
forever begin
#10 if (m_tlm_fifo.is_full ())
`uvm_info ("COMPB", "componentB:TLM_Fifo is now FULL !", UVM_MEDIUM)
end
endtask
endclass

Top Env/Test

端口与其实现之间的连接必须在更高的层次结构中进行。由于在此示例中两个组件都直接实例化于测试类内,它们之间的连接可以在测试的connect_phase阶段完成。如果这两个组件实例化于另一个组件或环境中,则必须在该组件或环境的connect_phase阶段进行连接。

class my_test extends uvm_env;
`uvm_component_utils (my_test)

componentA compA;
componentB compB;
int m_num_tx;

function new (string name = "my_test", uvm_component parent = null);
super.new (name, parent);
endfunction

virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
compA = componentA::type_id::create("componentA", this);
compB = componentB::type_id::create("componentB", this);

std::randomize(m_num_tx) with { m_num_tx inside {[4:10]}; };
`uvm_info("TEST", $sformatf("Create %0d packets in total", m_num_tx), UVM_LOW)
compA.m_num_tx = m_num_tx;
compB.m_num_tx = m_num_tx;
endfunction

// Connect the ports to the export of FIFO.
virtual function void connect_phase (uvm_phase phase);
compA.m_put_port.connect(compB.m_put_export);
endfunction

virtual task run_phase(uvm_phase phase);
super.run_phase(phase);
// Let all components finish for purpose of illustration
phase.raise_objection(this);
#1000;
phase.drop_objection(this);
endtask
endclass

 Simulation Log

UVM_INFO @ 0: reporter [RNTST] Running test my_test…
UVM_INFO testbench.sv(220) @ 0: uvm_test_top [TEST] Create 4 packets in total
UVM_INFO testbench.sv(48) @ 50: uvm_test_top.componentA.m_subcomp_1 [SUBCOMP1] Packet sent to compA:tlm_fifo
pkt: (Packet@2663) { addr: 'h1f data: 'h31 }
UVM_INFO testbench.sv(79) @ 100: uvm_test_top.componentA.m_subcomp_2 [SUBCOMP2] Packet received from compA:tlm_fifo, forward it
pkt: (Packet@2663) { addr: 'h1f data: 'h31 }
UVM_INFO testbench.sv(48) @ 100: uvm_test_top.componentA.m_subcomp_1 [SUBCOMP1] Packet sent to compA:tlm_fifo
pkt: (Packet@2685) { addr: 'hf4 data: 'h91 }
UVM_INFO testbench.sv(48) @ 150: uvm_test_top.componentA.m_subcomp_1 [SUBCOMP1] Packet sent to compA:tlm_fifo
pkt: (Packet@2699) { addr: 'hab data: 'ha8 }
UVM_INFO testbench.sv(126) @ 150: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 160: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 170: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 180: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 190: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(154) @ 200: uvm_test_top.componentB.m_subcomp_3 [SUBCOMP3] Packet received from componentA
pkt: (Packet@2663) { addr: 'h1f data: 'h31 }
UVM_INFO testbench.sv(79) @ 200: uvm_test_top.componentA.m_subcomp_2 [SUBCOMP2] Packet received from compA:tlm_fifo, forward it
pkt: (Packet@2685) { addr: 'hf4 data: 'h91 }
UVM_INFO testbench.sv(48) @ 200: uvm_test_top.componentA.m_subcomp_1 [SUBCOMP1] Packet sent to compA:tlm_fifo
pkt: (Packet@2681) { addr: 'h77 data: 'he7 }
UVM_INFO testbench.sv(126) @ 200: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 210: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 220: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 230: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 240: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 250: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 260: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 270: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 280: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 290: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(79) @ 300: uvm_test_top.componentA.m_subcomp_2 [SUBCOMP2] Packet received from compA:tlm_fifo, forward it
pkt: (Packet@2699) { addr: 'hab data: 'ha8 }
UVM_INFO testbench.sv(198) @ 300: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 310: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 320: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 330: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 340: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 350: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 360: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 370: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 380: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 390: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(154) @ 400: uvm_test_top.componentB.m_subcomp_3 [SUBCOMP3] Packet received from componentA
pkt: (Packet@2685) { addr: 'hf4 data: 'h91 }
UVM_INFO testbench.sv(79) @ 400: uvm_test_top.componentA.m_subcomp_2 [SUBCOMP2] Packet received from compA:tlm_fifo, forward it
pkt: (Packet@2681) { addr: 'h77 data: 'he7 }
UVM_INFO testbench.sv(198) @ 400: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 410: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 420: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 430: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 440: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 450: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 460: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 470: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 480: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 490: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 500: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 510: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 520: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 530: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 540: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 550: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 560: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 570: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 580: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 590: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(154) @ 600: uvm_test_top.componentB.m_subcomp_3 [SUBCOMP3] Packet received from componentA
pkt: (Packet@2699) { addr: 'hab data: 'ha8 }
UVM_INFO testbench.sv(154) @ 800: uvm_test_top.componentB.m_subcomp_3 [SUBCOMP3] Packet received from componentA
pkt: (Packet@2681) { addr: 'h77 data: 'he7 }
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_objection.svh(1271) @ 1000: 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) @ 1000: reporter [UVM/REPORT/SERVER]
— UVM Report Summary —

赞(0)
未经允许不得转载:网硕互联帮助中心 » uvm-tlm-example
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!