以 C++ 编写流量生成器 - 2022.1 简体中文

Vitis 统一软件平台文档 应用加速开发 (UG1393)

Document ID
UG1393
Release Date
2022-05-25
Version
2022.1 简体中文
  • 对于 C++,API 可从以下位置获取:
    $XILINX_VIVADO/data/emulation/ip_utils/xtlm_ipc/xtlm_ipc_v1_0/cpp/inc/axis

    C++ API 可提供阻塞和非阻塞函数支持。以下片段显示了其用法。

    提示: 此外还提供了一个 Makefile 样本用于生成可执行文件。
  • 阻塞发送:
    如果您倾向于不使用细粒度控制(建议),则可使用一个简单的 API:
    #include "xtlm_ipc.h" //Include file
    void send_data() 
    {
     //! Instantiate IPC socket with name matching in IPI diagram...
     xtlm_ipc::axis_initiator_socket_util<xtlm_ipc::BLOCKING> socket_util("gt_master");
     const unsigned int NUM_TRANSACTIONS = 8;
     std::vector<char> data;
     std::cout << "Sending " << NUM_TRANSACTIONS << " data transactions..." <<std::endl;
     for(int i = 0; i < NUM_TRANSACTIONS; i++) {
     data = generate_data();
     print(data);
     socket_util.transport(data.data(), data.size());
     }
    }

    对于需要对 AXI4-Stream 进行细粒度控制的高级用户,可使用:

    #include "xtlm_ipc.h" //Include file
     
    void send_packets()
    {
        //! Instantiate IPC socket with name matching in IPI diagram...
        xtlm_ipc::axis_initiator_socket_util<xtlm_ipc::BLOCKING> socket_util("gt_master");
     
        const unsigned int NUM_TRANSACTIONS = 8;
        xtlm_ipc::axi_stream_packet packet;
     
        std::cout << "Sending " << NUM_TRANSACTIONS << " Packets..." <<std::endl;
        for(int i = 0; i < NUM_TRANSACTIONS; i++) {
            xtlm_ipc::axi_stream_packet packet;
            // generate_data() is your custom code to generate traffic 
            std::vector<char> data = generate_data();
            //! Set packet attributes...
            packet.set_data(data.data(), data.size());
            packet.set_data_length(data.size());
            packet.set_tlast(1);
            //Additional AXIS attributes can be set if required
            socket_util.transport(packet); //Blocking transport API to send the transaction
        }
    }
  • 阻塞接收:
    如果您倾向于不使用细粒度控制(建议),则可使用一个简单的 API:
    #include "xtlm_ipc.h" //Include file
    void receive_data()
    {
     //! Instantiate IPC socket with name matching in IPI diagram...
     xtlm_ipc::axis_target_socket_util<xtlm_ipc::BLOCKING> socket_util("gt_slave");
     const unsigned int NUM_TRANSACTIONS = 100;
     unsigned int num_received = 0;
     std::vector<char> data;
     std::cout << "Receiving " << NUM_TRANSACTIONS << " data transactions..." <<std::endl;
     while(num_received < NUM_TRANSACTIONS) {
     socket_util.sample_transaction(data);
     print(data);
     num_received += 1;
     }
    }

    对于需要对 AXI4-Stream 进行细粒度控制的高级用户,可使用:

    #include "xtlm_ipc.h"
     
    void receive_packets()
    {
        //! Instantiate IPC socket with name matching in IPI diagram...
        xtlm_ipc::axis_target_socket_util<xtlm_ipc::BLOCKING> socket_util("gt_slave");
     
        const unsigned int NUM_TRANSACTIONS = 8;
        unsigned int num_received = 0;
        xtlm_ipc::axi_stream_packet packet;
     
        std::cout << "Receiving " << NUM_TRANSACTIONS << " packets..." <<std::endl;
        while(num_received < NUM_TRANSACTIONS) {
            socket_util.sample_transaction(packet); //API to sample the transaction
            //Process the packet as per requirement.
            num_received += 1;
        }
    }
  • 非阻塞发送:
    #include <algorithm>    // std::generate
    #include "xtlm_ipc.h"
     
    //A sample implementation of generating random data.
    xtlm_ipc::axi_stream_packet generate_packet()
    {
        xtlm_ipc::axi_stream_packet packet;
        // generate_data() is your custom code to generate traffic
        std::vector<char> data = generate_data();
     
        //! Set packet attributes...
        packet.set_data(data.data(), data.size());
        packet.set_data_length(data.size());
        packet.set_tlast(1);
        //packet.set_tlast(std::rand()%2);
        //! Option to set tuser tkeep optional attributes...
     
        return packet;
    }
     //Simple Usage
    
    void send_data() 
    {
        //! Instantiate IPC socket with name matching in IPI diagram...
        xtlm_ipc::axis_initiator_socket_util<xtlm_ipc::NON_BLOCKING> socket_util("gt_master");
    
        const unsigned int NUM_TRANSACTIONS = 8;
        std::vector<char> data;
    
        std::cout << "Sending " << NUM_TRANSACTIONS << " data transactions..." <<std::endl;
        for(int i = 0; i < NUM_TRANSACTIONS/2; i++) {
            data = generate_data();
            print(data);
            socket_util.transport(data.data(), data.size());
        }
    
        std::cout<< "Adding Barrier to complete all outstanding transactions..." << std::endl;
        socket_util.barrier_wait();
        for(int i = NUM_TRANSACTIONS/2; i < NUM_TRANSACTIONS; i++) {
            data = generate_data();
            print(data);
            socket_util.transport(data.data(), data.size());
        }
    }
    void send_packets()
    {
        //! Instantiate IPC socket with name matching in IPI diagram...
        xtlm_ipc::axis_initiator_socket_util<xtlm_ipc::NON_BLOCKING> socket_util("gt_master"); 
        // Instantiate Non Blocking specialization
     
        const unsigned int NUM_TRANSACTIONS = 8;
        xtlm_ipc::axi_stream_packet packet;
     
        std::cout << "Sending " << NUM_TRANSACTIONS << " Packets..." <<std::endl;
        for(int i = 0; i < NUM_TRANSACTIONS; i++) {
            packet = generate_packet(); // Or user's test patter / live data etc.
            socket_util.transport(packet);
        }
    }
  • 非阻塞接收:
    #include <unistd.h>
    #include "xtlm_ipc.h"
    //Simple Usage 
    void receive_data()
    {
        //! Instantiate IPC socket with name matching in IPI diagram...
        xtlm_ipc::axis_target_socket_util<xtlm_ipc::NON_BLOCKING> socket_util("gt_slave");
    
        const unsigned int NUM_TRANSACTIONS = 8;
        unsigned int num_received = 0, num_outstanding = 0;
        std::vector<char> data;
    
        std::cout << "Receiving " << NUM_TRANSACTIONS << " data transactions..." <<std::endl;
        while(num_received < NUM_TRANSACTIONS) {
            num_outstanding = socket_util.get_num_transactions();
            num_received += num_outstanding;
            
            if(num_outstanding != 0) {
                std::cout << "Outstanding data transactions = "<< num_outstanding <<std::endl;
                for(int i = 0; i < num_outstanding; i++) {
                    socket_util.sample_transaction(data);
                    print(data);
                }
            }
            usleep(100000);
        }
    }
    void receive_packets()
    {
        //! Instantiate IPC socket with name matching in IPI diagram...
        xtlm_ipc::axis_target_socket_util<xtlm_ipc::NON_BLOCKING> socket_util("gt_slave");
     
        const unsigned int NUM_TRANSACTIONS = 8;
        unsigned int num_received = 0, num_outstanding = 0;
        xtlm_ipc::axi_stream_packet packet;
     
        std::cout << "Receiving " << NUM_TRANSACTIONS << " packets..." <<std::endl;
        while(num_received < NUM_TRANSACTIONS) {
            num_outstanding = socket_util.get_num_transactions();
            num_received += num_outstanding;
             
            if(num_outstanding != 0) {
                std::cout << "Outstanding packets = "<< num_outstanding <<std::endl;
                for(int i = 0; i < num_outstanding; i++) {
                    socket_util.sample_transaction(packet);
                    print(packet);
                }
            }
            usleep(100000); //As transaction is non-blocking we would like to give some delay between consecutive samplings
        }
    }
  • 以下是用于上述阻塞接收的 Makefile 示例:
    GCC=/usr/bin/g++
    IPC_XTLM=$(XILINX_VIVADO)/data/emulation/ip_utils/xtlm_ipc/xtlm_ipc_v1_0/cpp/
    PROTO_PATH=$(XILINX_VIVADO)/data/simmodels/xsim/2022.1/lnx64/6.2.0/ext/protobuf/
     
    SRC_FILE=b_receive.cpp
    .PHONY: run all
     
    default: all
     
    all : b_receive
     
    b_receive: $(SRC_FILE)
    $(GCC)   $(SRC_FILE) $(IPC_XTLM)/src/common/*.cpp -I$(IPC_XTLM)/inc/ -I$(PROTO_PATH)/include/ -L$(PROTO_PATH) -lprotobuf -L$IPC_XTLM/lib/ -lxtlm_ipc -o $@ -lpthread -I$(BOOST)/
    
  • 对于 C API,可从以下位置获取此文件:
    $XILINX_VIVADO/data/emulation/ip_utils/xtlm_ipc/xtlm_ipc_v1_0/C/inc/axis/c_axis_socket.h
    可基于以下位置的预编译库来链接此文件:
    $XILINX_VIVADO/data/emulation/ip_utils/xtlm_ipc/xtlm_ipc_v1_0/C/lib/

在以下位置可找到完整的系统级示例:https://github.com/Xilinx/Vitis_Accel_Examples/tree/master/emulation