TLM 2.0引入了套接字(Socket)機制,實現發起方(initiator)與目標方(target)組件間的異步雙向數據傳輸。套接字與端口(port)和導出(export)同源,均繼承自uvm_port_base基類。發起事務的組件使用發起方套接字(initiator socket),稱為發起方;接收事務的組件使用目標方套接字(target socket),稱為目標方。需注意:發起方套接字僅能連接目標方套接字,目標方套接字僅能連接發起方套接字。
TestBench
?
讓我們來看看啟動器組件,了解套接字是如何聲明和使用的。b_transport() 方法中使用的時序注解參數允許時序點從調用和返回任務的仿真時間中偏移。
class initiator extends uvm_component;`uvm_component_utils (initiator)// Declare a blocking transport socket (using initiator socket class)uvm_tlm_b_initiator_socket #(simple_packet) initSocket;uvm_tlm_time delay;simple_packet pkt;function new (string name = "initiator", uvm_component parent= null);super.new (name, parent);endfunctionvirtual function void build_phase (uvm_phase phase);super.build_phase (phase);// Create an instance of the socketinitSocket = new ("initSocket", this);delay = new ();endfunctionvirtual task run_phase (uvm_phase phase);// Let us generate 5 packets and send it via socketrepeat (5) beginpkt = simple_packet::type_id::create ("pkt");assert(pkt.randomize ());`uvm_info ("INIT", "Packet sent to target", UVM_LOW)pkt.print (uvm_default_line_printer);// Use the socket to send datainitSocket.b_transport (pkt, delay);endendtask
endclass
考慮目標套接字,你會發現它與我們在前幾次課程中看到的端口和導出方案非常相似。
class target extends uvm_component;`uvm_component_utils (target)// Declare a blocking target socketuvm_tlm_b_target_socket #(target, simple_packet) targetSocket;function new (string name = "target", uvm_component parent = null);super.new (name, parent);endfunctionvirtual function void build_phase (uvm_phase phase);super.build_phase (phase);// Create an instance of the target sockettargetSocket = new ("targetSocket", this);endfunction// Provide the implementation method of b_transport in the target classtask b_transport (simple_packet pkt, uvm_tlm_time delay);`uvm_info ("TGT", "Packet received from Initiator", UVM_MEDIUM)pkt.print (uvm_default_line_printer);endtask
endclass
缺失的一環是兩個套接字之間的連接,而實現這一連接的最佳位置是在初始化器和目標組件都被實例化的環境中。
class my_env extends uvm_env;`uvm_component_utils (my_env)initiator init;target tgt;function new (string name = "my_env", uvm_component parent = null);super.new (name, parent);endfunctionvirtual function void build_phase (uvm_phase phase);super.build_phase (phase);// Create an object of both componentsinit = initiator::type_id::create ("init", this);tgt = target::type_id::create ("tgt", this);endfunction// Connect both sockets in the connect_phasevirtual function void connect_phase (uvm_phase phase);init.initSocket.connect (tgt.targetSocket);endfunction
endclass