2. Vitis工程创建

好,咱们进入正题。这一章我带你亲手创建Vitis工程。说实话,很多初学者卡在这一步——不是代码写不出来,而是工程结构没搞明白。我当年第一次用Vitis时,光是理解xpfm和xclbin这两个文件就折腾了两天。今天咱们把它彻底讲透。

2.1 创建Vitis平台工程

平台工程是什么?说白了,它就是硬件和软件之间的“翻译官”。你的加速器要跑在FPGA上,CPU要跟它通信,DDR要分配地址——这些信息都打包在平台里。

创建步骤其实不复杂:

  1. 打开Vitis,点击 Create Platform Project
  2. 选择你的硬件描述文件(.xsa),这个文件由Vivado生成
  3. 配置操作系统(一般选standalone或Linux)
  4. 指定处理器类型(比如Cortex-A53、RISC-V等)
我的习惯:平台工程的名字最好跟项目名一致,别用“test”、“demo”这种名字。我在一个项目里吃过亏,三个月后回来看代码,完全想不起这个平台是干嘛用的。

平台工程创建完成后,你会看到这样一个目录结构:

my_platform/
├── hardware/
│   └── my_platform.xsa
├── software/
│   └── standalone/
│       ├── boot/
│       └── libsrc/
├── platform.spr
└── xpfm/
    └── my_platform.xpfm

嗯,这里要注意:platform.spr是Vitis的内部项目文件,别手贱去改它。我见过有人用文本编辑器打开它,然后工程就崩了。

2.2 创建Vitis应用工程

平台搭好了,接下来就是写应用。应用工程就是你的加速器代码、主机代码、以及它们之间的“胶水代码”。

创建步骤:

  1. 在Vitis中点击 Create Application Project
  2. 选择刚才创建的平台工程
  3. 选择模板(比如“Empty Application”或“Vector Addition”)
  4. 配置编译选项(优化级别、调试信息等)
关键点:应用工程必须依赖一个平台工程。没有平台,你的代码就不知道往哪个FPGA上跑。这就像你写了个APP,但不知道装在哪台手机上。

应用工程的结构大概是这样的:

my_app/
├── src/
│   ├── host/
│   │   └── main.cpp
│   └── kernel/
│       └── vadd.cpp
├── system_hw_link/
│   └── system_hw_link.xsa
└── Makefile

我曾经犯过一个低级错误:把主机代码和内核代码混在一起放。结果编译时链接器报了一堆莫名其妙的错误。后来我养成了习惯——src/host和src/kernel严格分开。

2.3 理解xpfm平台描述文件

xpfm文件,全称是“Xilinx Platform Metadata”。它本质上是一个XML文件,描述了平台的硬件资源。

打开一个xpfm文件,你会看到类似这样的内容:

<?xml version="1.0" encoding="UTF-8"?>
<platform>
  <project name="my_platform" version="1.0">
    <hardware>
      <device part="xc7z020clg400-1"/>
      <memory name="DDR" address="0x40000000" size="0x40000000"/>
    </hardware>
    <software>
      <os name="standalone"/>
      <processor name="ps7_cortexa9_0"/>
    </software>
  </project>
</platform>

这里面最重要的几个字段:

字段 含义 我的备注
device part FPGA芯片型号 别搞错,Zynq和Kintex的管脚定义完全不同
memory DDR地址空间 地址范围决定了你能用多少内存
processor 处理器类型 ARM还是RISC-V?决定了你的交叉编译器
避坑指南:我曾经在xpfm里把DDR地址写错了,结果加速器读写数据时一直访问到无效地址。排查了整整一天才发现是这里的问题。所以,每次修改xpfm后,一定要用Vitis的验证工具检查一遍。

2.4 理解xclbin二进制文件

xclbin是Xilinx的二进制加速器文件。它包含了FPGA的比特流、内核描述、以及元数据。

生成xclbin的过程是这样的:

  1. 编写内核代码(C/C++或HLS)
  2. 用Vitis编译器编译成.xo文件
  3. 用Vitis链接器将.xo文件和平台链接,生成.xclbin

你可以用xclbinutil工具查看xclbin的内容:

xclbinutil --dump-section all --input my_accel.xclbin

输出会显示:

  • 内核名称和接口
  • 使用的FPGA资源(LUT、BRAM、DSP等)
  • 时钟频率
  • 内存映射关系
小技巧:调试时,我经常用xclbinutil检查生成的xclbin是否包含了正确的内核。有一次我发现内核接口类型不对——应该是AXI4-Stream,结果配成了AXI4-Lite。这种错误在运行时才会暴露,但用工具提前检查就能发现。

xclbin和xpfm的关系,我用一张图来说明:

Vitis工程核心文件关系图 平台工程 硬件描述 (.xsa) 软件配置 (standalone/Linux) 输出:xpfm 文件 应用工程 主机代码 (C++) 内核代码 (HLS/C) 输出:xclbin 文件 依赖 运行时 xpfm 描述硬件资源 + xclbin 加载加速器 xpfm 告诉系统“我有什么硬件”,xclbin 告诉系统“我要用什么加速器”

你看,xpfm是平台的“身份证”,xclbin是加速器的“可执行文件”。两者缺一不可。

最后总结一下:创建Vitis工程,本质上就是三步——搭平台、写应用、生成二进制。平台描述硬件能力,应用实现具体功能,xclbin是最终交付物。我在实际项目中,通常会把平台工程放在Git仓库的一个独立分支里,应用工程放在另一个分支。这样平台升级时,应用代码可以独立迭代。

好了,这一章的内容就到这里。记住:工程创建是基础,基础不牢,地动山摇。下一章咱们会深入内核开发,到时候你会感谢今天认真搭建的工程结构。

核心要点回顾:
  • 平台工程 = 硬件描述 + 软件配置 → 输出xpfm
  • 应用工程 = 主机代码 + 内核代码 → 输出xclbin
  • xpfm是静态描述,xclbin是动态加载
  • 用xclbinutil检查生成的二进制文件,避免低级错误

可可精品资料库