FPGA学习(自用)

1. 核心架构:异构计算模型 🧠

  • Host (主机端):运行在服务器 CPU 上,使用标准 C++ 和 XRT 库编写。负责数据准备、内存分配以及调度底层硬件。

  • Kernel (内核端):运行在 U280 FPGA 上,负责实际的并行加速计算。通过 Vitis HLS 工具,可以用 C/C++ 来描述硬件逻辑。

2. Kernel 端开发 (硬件接口映射) ⚡

为了让 C++ 循环变成 U280 上的真实电路,我们使用了 #pragma 编译指示:

  • m_axi (高带宽内存接口) :负责海量数据传输。我们将数组绑定到不同的物理通道(如 gmem0, gmem1),让 FPGA 能够同时从 HBM 内存中读写不同数据,实现并行。

  • s_axilite (轻量级控制接口) :负责控制信号和参数传递。我们将指针基地址、标量(如长度 N)以及启动/停止信号统一绑定到 control 寄存器上,供 CPU 读写。

3. Host 端开发 (XRT 控制逻辑) 💻

主机程序扮演着"指挥官"的角色,核心数据流转包括四个步骤:

  1. 创建 Buffer 📦:在 U280 的 HBM 内存中按字节数分配缓冲区,为数据"占座"。

  2. H2D 传输 (Host to Device):通过 PCIe 总线,将待计算的数据从 CPU 内存搬运到 FPGA 的 HBM 中。

  3. 触发执行 :传递参数并下达执行指令,CPU 通过 wait() 指令等待 FPGA 闪电般的计算完成。

  4. D2H 传输 (Device to Host):将计算结果从 FPGA 的 HBM 搬运回 CPU 内存,供后续打印或保存。

4. 编译与仿真工作流 🛠️

  • 编译产物 :Host 代码被编译为普通的可执行文件(如 host_app),Kernel 代码被编译为硬件配置压缩包(.xclbin )。在终端运行时,将 .xclbin 作为参数传给 host_app 来启动整个系统。

  • 平台 (Platform) :编译时必须指定目标平台(如 xilinx_u280_...),它包含了板卡的底层硬件拓扑结构。

  • 阶梯式开发

    • sw_emu (软件仿真):秒级编译,完全在 CPU 上运行,专用于快速验证算法逻辑的正确性。

    • hw_emu (硬件仿真):模拟底层硬件时序,用于评估周期和通道拥堵情况。

    • hw (纯硬件):耗时数小时进行综合与布线,生成最终部署到 U280 物理板卡上的文件。

异构计算(简单了解)
异构编程生态

学习 XRT (Xilinx Runtime) Native C++ API 是非常明智的选择,它是 AMD/Xilinx

官方目前主推的、比 OpenCL 更轻量且更符合现代 C++ 规范的接口。

以下是系统学习 XRT Native API 的路径和核心知识点:

1. 核心概念对比(从 OpenCL 迁移)

理解 XRT Native API 最快的方法是将其与你当前工程中的 OpenCL 概念进行对比: ┌────────────┬────────────────────────────┬─────────────────────────────────┐

功能OpenCL API (旧)XRT Native API (新)

├────────────┼────────────────────────────┼─────────────────────────────────┤

设备对象 │ cl::Device │ `xrt::device`

│ **加载硬... │ cl::Program │ `xrt::uuid` (通过 `device.load_x...

内核对象 │ cl::Kernel │ `xrt::kernel`

内存缓冲区 │ cl::Buffer │ `xrt::bo` (Buffer Object)

数据同步 │ enqueueMigrateMemObjects │ `bo.sync()`

执行内核 │ `cl::CommandQueue::enqueu... │ `kernel()` (像函数一样直接调用)

└────────────┴────────────────────────────┴─────────────────────────────────┘

2. 最小代码框架 (Hello World)

一个典型的 XRT Native C++ 主机端程序逻辑如下:

cpp 复制代码
// ==========================================
// 传统 OpenCL API 主机端代码示例 (极度简化版)
// ==========================================

// 1. 获取平台和设备
cl_platform_id platform;
clGetPlatformIDs(1, &platform, NULL);
cl_device_id device;
clGetDeviceIDs(platform, CL_DEVICE_TYPE_ACCELERATOR, 1, &device, NULL);

// 2. 创建上下文和命令队列 (繁琐的初始化)
cl_context context = clCreateContext(0, 1, &device, NULL, NULL, NULL);
cl_command_queue q = clCreateCommandQueue(context, device, 0, NULL);

// 3. 加载 xclbin 硬件比特流并创建 Program (省略了读取文件的几十行代码)
cl_program program = clCreateProgramWithBinary(context, 1, &device, &fileBufSize, (const unsigned char**)&fileBuf, NULL, NULL);

// 4. 创建内核
cl_kernel kernel = clCreateKernel(program, "vadd", NULL);

// 5. 在 FPGA 显存中分配 Buffer
cl_mem buffer_in1 = clCreateBuffer(context, CL_MEM_READ_ONLY, size_in_bytes, NULL, NULL);
cl_mem buffer_in2 = clCreateBuffer(context, CL_MEM_READ_ONLY, size_in_bytes, NULL, NULL);
cl_mem buffer_out = clCreateBuffer(context, CL_MEM_WRITE_ONLY, size_in_bytes, NULL, NULL);

// 6. 逐个设置内核参数 (非常容易出错,写错索引直接崩溃)
clSetKernelArg(kernel, 0, sizeof(cl_mem), &buffer_in1);
clSetKernelArg(kernel, 1, sizeof(cl_mem), &buffer_in2);
clSetKernelArg(kernel, 2, sizeof(cl_mem), &buffer_out);
clSetKernelArg(kernel, 3, sizeof(int), &size);

// 7. 将数据从主机拷贝到 FPGA,并排队执行内核
clEnqueueWriteBuffer(q, buffer_in1, CL_TRUE, 0, size_in_bytes, host_in1, 0, NULL, NULL);
clEnqueueWriteBuffer(q, buffer_in2, CL_TRUE, 0, size_in_bytes, host_in2, 0, NULL, NULL);
clEnqueueTask(q, kernel, 0, NULL, NULL); // 触发执行

// 8. 等待执行完毕并读回结果
clEnqueueReadBuffer(q, buffer_out, CL_TRUE, 0, size_in_bytes, host_out, 0, NULL, NULL);
clFinish(q);

// 9. 手动清理所有资源 (如果中途报错退出,这里没执行就会内存泄漏)
clReleaseMemObject(buffer_in1);
clReleaseMemObject(buffer_in2);
clReleaseMemObject(buffer_out);
clReleaseKernel(kernel);
clReleaseProgram(program);
clReleaseCommandQueue(q);
clReleaseContext(context);

3. 核心学习资源 (必读)

  1. 官方文档 UG1393 (Vitis 用户指南)

* 重点阅读 "XRT Native API" 章节。这是最权威的参考资料。

  1. XRT 入门示例 (GitHub)

* 访问 Xilinx/Vitis_Accel_Examples

(https://github.com/Xilinx/Vitis_Accel_Examples)。

* 搜索标注有 xrt_native 的示例(通常在 host/ 目录下可以看到使用了

xrt_kernel.h 而非 xcl2.hpp 的代码)。

  1. XRT 官方 API 文档

* 访问 xilinx.github.io/XRT/

(https://xilinx.github.io/XRT/master/html/index.html),查看完整的 C++

API 引用手册。

4. 实践建议

* 环境准备:确保你的系统中安装了 xrt-dev 包。在代码中包含头文件

<xrt/xrt_device.h>。

* 编译设置:在 Makefile 中,你需要链接 xrt_coreutil 库。

* 编译选项添加:-I$(XILINX_XRT)/include

* 链接选项添加:-L$(XILINX_XRT)/lib -lxrt_coreutil

* 从模仿开始:你可以试着把你现在工程里

Vitis_workflow/examples/vadd_vmul/host/host.cpp 的 OpenCL 代码改写成 XRT

Native 版本。你会发现代码量会减少 30% 以上,逻辑更清晰。

总结

学习 XRT Native API 的门槛比 OpenCL

低得多,因为它隐藏了大量底层的样板代码。如果你已经理解了"内存申请 -> 数据搬运

-> 启动内核 -> 传回结果"这个流程,只需花 1-2 天 熟悉 xrt::device、xrt::bo 和

xrt::kernel 这几个类即可上手。

相关推荐
国科安芯11 小时前
芯片抗单粒子性能研究及其在商业卫星测传一体机中的应用
嵌入式硬件·安全·fpga开发·性能优化·硬件架构
szxinmai主板定制专家18 小时前
RK3588 8个USB工控解决方案,适用于机器视觉,工业互联等
arm开发·人工智能·fpga开发
Aaron15881 天前
RFSOC与ADRV9009、AD9026、AD9361技术指标及应用场景对比分析
人工智能·算法·fpga开发·硬件工程·信息与通信·信号处理·基带工程
忙碌5442 天前
实战指南:如何用Docker+Kubernetes高效部署机器学习模型
fpga开发
国科安芯2 天前
实战验证:ASM1042S2S CANFD收发器的质子单粒子效应试验与在轨性能
网络·人工智能·单片机·嵌入式硬件·物联网·fpga开发
国科安芯2 天前
ASP4644S电源芯片引脚功能与参考设计输出电压计算方法
网络·单片机·嵌入式硬件·fpga开发·性能优化
fonx2 天前
ZYNQ7010备忘
fpga开发
悲喜自渡7213 天前
FPGA开发方式
fpga开发
芯门3 天前
FPGA商用级ISP(三):自动白平衡(AWB)算法实现与 FPGA 架构解析
图像处理·计算机视觉·fpga开发