PS端UpSample函数实现

PS端UpSample函数实现

目的

  • 在PS端dingyi一个函数,实现对PL端的UpSample模块的调用,完成对输入数据的上采样操作
  • UpSample模块的功能是将输入的13x13x128的数据上采样为26x26x128的数据,保持通道数不变
  • UpSample模块在YOLO网络中只有一层,位于第19层

步骤

  • 在PS端定义函数upsample_task

    • 在状态机中判断i==11时调用该函数
    • 在该函数中分为三个步骤:
      • 发送数据给PL端
      • 发送UpSample命令给PL端
      • 接收PL端返回的数据
  • 发送数据给PL端

    • 使用DMA写操作,将layer18的输出数据(13x13x128)发送给PL端
    • 发送地址为0x3000000,发送长度为0x548(1352字节)
    • 发送前需要发送ZeroPointIn命令,将ZeroPointIn设置为0(因为不需要减去ZeroPoint
  • 发送UpSample命令给PL端

    • 使用FUTURE_WRITE操作,将0x00000001写入0x40000000地址(对应计算器2的命令寄存器)
    • 这个命令会触发PL端的UpSample模块开始工作
  • 接收PL端返回的数据

    • 使用DMA读操作,从PL端读取上采样后的数据(26x26x128)
    • 读取地址为0x3100000,读取长度为0x1520(5408字节)
    • 由于输入通道数为128,需要分16次循环读取,每次读取8个通道的数据
    • 每次循环后,更新发送地址和接收地址

    由于输入数据有128个通道,而每次只能发送8个通道的数据,所以需要循环16次执行第二步中的三个子步骤,并且每次更新发送和接收的地址

例子

  • 假设layer18的输出数据为:
通道 数据
0 [1, 2, 3, …, 169]
1 [170, 171, 172, …, 338]
127 [21506, 21507, 21508, …, 21674]
  • 则发送给PL端的数据为:
地址 数据
0x3000000 [1, 2, 3, …, 169]
0x3000054 [170, 171, 172, …, 338]
0x30004FC [21506, 21507, 21508, …, 21674]
  • PL端接收到数据后,根据UpSample命令,将每个元素复制四次,形成26x26的矩阵,例如:
输入 输出
[1, 2, …, 13] [1, 1, 2, 2, …, 12, 12, 13, 13]
[157, …, 169] [157, 157, …, 168, 168, 169, 169]
  • PL端将上采样后的数据放到AXI接口上,等待PS端读取,例如:
地址 数据
0x3100000 [1, 1, …, 13, 13]
0x310151C [21662, …,21674]
  • PS端从PL端读取数据,每次读取8个通道的数据,共16次循环,例如:
循环次数 发送地址 接收地址 数据长度
i=0 0x3000000 0x3100000 0x1520
i=1 0x3000548 0x3101520 0x1520
i=15 0x3004FC8 0x3114F20 0x1520

image

流程(a):

graph TD A[修改 PL 端代码] --> B[生成bit文件] B --> C[定义 PS 端函数] C --> D[判断当前层] D -->|是| E[调用 UpSample 函数] D -->|否| F[执行状态机操作] E --> G[发送数据给 PL 端] G --> H[发送 UpSample 命令] H --> I[接收 PL 端数据] I --> J[存储到 layer 19 缓存] J --> K[验证结果]

流程(b):

sequenceDiagram participant PS participant PL Note over PS: 初始化参数和地址 loop i = 0 to 15 PS->>PL: 发送第 i 组数据 (8 个通道, 13x13) PS->>PL: 发送 Zero point 命令 (Zero point in = 0) PS->>PL: 发送 UpSample 命令 PL->>PS: 返回第 i 组数据 (8 个通道, 26x26) end Note over PS: 检查结果并导出 bit 文件
  • PL 端的 UpSample 模块代码:在 PL 端编写 UpSample 模块,该模块可以接收 PS 端发送的 13x13 的数据,并将其上采样为 26x26 的数据,然后通过 AXI 接口输出。修改一些参数和频率,以及生成比特文件
  • PS 端的 UpSample 函数代码:在 PS 端编写 UpSample 函数,该函数可以将输入的 128 个通道的 13x13 的数据分成 16 组,每组 8 个通道,然后依次发送给 PL 端的 UpSample 模块,并接收返回的 26x26 的数据。设置一些地址和长度,以及发送 Zero point 命令
  • PS 端的 UpSample 函数调试:在 VITIS 中设置调试选项,下载比特文件,运行程序,并检查结果。比较 PS 端接收到的数据和期望的数据之间的差异

代码框架:

void upsample_task() {
    // 定义配置参数
    int input_channel = 128;
    int output_channel = 128;
    int input_size = 13;
    int output_size = 26;

    // 定义发送和接收地址
    int tx_addr = TX_BASE_ADDR; // 假设 TX_BASE_ADDR 是 0x3000000
    int rx_addr = RX_BASE_ADDR; // 假设 RX_BASE_ADDR 是 0x3100000

    // 定义发送和接收长度
    int tx_len = input_size * input_size * 8; // 每次发送8个通道的数据
    int rx_len = output_size * output_size * 8; // 每次接收8个通道的数据

    // 定义命令和中断信号
    int upsample_cmd = 0x00000001; // 表示执行UpSample操作
    int zero_point_in_cmd = 0x00000000; // 表示Zero point in为0
    int interrupt_sig; // 表示中断信号

    // 使用 for 循环处理所有通道的数据
    for (int i = 0; i < input_channel / 8; i++) {
        // 发送数据给 PL 端
        dma_write(tx_addr, tx_len, input_data); // 假设 input_data 是 PS 端的输入数据
        // 发送命令给 PL 端
        axi_lite_write(0x43C00000, upsample_cmd); // 假设 0x43C00000 是 PL 端的命令地址
        axi_lite_write(0x43C00004, zero_point_in_cmd); // 假设 0x43C00004 是 PL 端的 Zero point in 地址
        // 接收数据从 PL 端
        dma_read(rx_addr, rx_len, output_data); // 假设 output_data 是 PS 端的输出数据
        // 接收中断信号从 PL 端
        axi_lite_read(0x43C00008, interrupt_sig); // 假设 0x43C00008 是 PL 端的中断信号地址
        // 更新发送和接收地址
        tx_addr += tx_len;
        rx_addr += rx_len;
    }
}
posted @ 2023-08-22 19:50  李白的白  阅读(105)  评论(0编辑  收藏  举报