FPGA-CPU异构系统软硬件联合开发与测试

FPGA-CPU异构系统软硬件联合开发与测试

综述

当前高端工业与航天算力领域的电子学控制基座逐渐转向CPU-FPGA联合异构系统。该类系统一般通过PCIe总线或者以太网进行通信,其上的软件开发实质上分为FPGA软件和CPU软件。其中,FPGA软件基于HDL语言的硬件描述特性,这种“软件”也并非传统意义的软件,更多类似于一种“软化的硬件”;CPU软件则更倾向于集成化与基座统一化。

一般来说,FPGA软件由VHDL或者VerilogHDL语言编写,作为一种硬件电路的描述被加载到FPGA上运行。得益于现代总线系统(如AMBA、LocalBus总线等),不同的电路模块(简称IP)之间可以使用标准总线进行连接。这对于复杂系统的模块化设计和各单元的解耦也有很大益处,同时也为自动化测试提供了良好的插入点。

CPU软件在复杂系统中倾向于使用“底座系统+定制驱动+应用程序”的模式。底座系统一般采用Linux或者一些经过深度定制的实时系统:就Linux而言,一般CPU厂商都会从LTS版本中分支一个版本进行深度定制开发,将CPU的私有驱动件融合到Linux主线内核中,并且发布针对于厂商CPU的版本;深度定制的实时系统例如国产的天脉系统,则更注重于系统本身实时性与稳定性的优化。一个很好的例子是飞腾(Phytium,国产ARM64兼容CPU与SoC厂商),其发布了一整套可以在CPU平台上进行全流程开发的SDK(详见
Gitee 飞腾嵌入式软件部
),包括buildroot和Yocto开发环境与工具链。

定制驱动,一般指下游开发者为特定硬件开发的私有驱动,比如FPGA的PCIe驱动、一些集成化系统的驱动程序等。一个很好的例子是AMD的XDMA系统。该系统在FPGA上提供了基于AXI4-MM界面的接口,可以通过互联组件连接到DDR或者其他IP的配置地址空间,支持SGDMA和Bypass两种读写模式,为大规模传输和低延迟传输提供了适用于各自场景的解决方案;在CPU端提供了一整套驱动程序,直接编译成内核模块加载到Linux内核即可使用,真正实现了CPU-FPGA异构系统的开箱即用。

应用程序,就是指用于实现上层业务功能的端侧应用程序,或者为上层业务功能提供支持的库和框架。应用程序一般在Linux的应用层运行,用于实现复杂控制、网络接口、人机交互等功能。

综上,在复杂系统的开发过程中,必然会面临各种测试问题。本文的目的是,为该类开发提供一种从FPGA的IP到CPU应用软件的全栈自动化测试接口方案。

目前,AI辅助编程已经对该类全系统开发与测试的方式提供了一种全新的解决方案。本文将会基于AI辅助编程的相关方法,结合已有的一些测试框架、测试方法,在固化流程尽量使用确定性代码和工具、在不确定或者可变流程中使用适度的且边界可限制的AI参与,提出一个需要合理的人工干预、回归测试尽量自动化且可以稳定浮现的方法。

FPGA的IP化开发与回归测试

系统设计

在复杂异构系统中,FPGA需要实现数据处理链路,并且将可以配置的参数成功暴露到AXI地址空间。一般来说,XDMA会提供SGDMA和Bypass这两个AXI-MM主接口,外设需要通过互联组件将自身的配置地址空间连接到这两个主接口之一。一般来说,DDR或者HBM应当连接到SGDMA主接口(除非需要FPGA与其他设备进行P2P通信),配置寄存器使用Bypass主接口,并使用不同的基地址区分不同的储存区或者不同IP的配置地址区域。

IP设计方法论

第一步,单个的IP必须确定好功能、定好接口。比如想要实现一个对图像实行二值化的IP,就要规划好必须具有两个AXI-Stream接口,一个输入一个输出;然后使用一个AXI-Lite从接口进行参数配置,比如二值化的阈值。如果需要使用中断通知CPU的话还要根据XDMA的中断过程做好中断的发出与应答时序规划。一般来说,IP的外部接口需要尽快定型,比如有几个AXI接口、几个中断接口;AXI-Lite配置空间的寄存器可以边写边定。

第二步,将IP设计文档写好、IP的框架搭好。这一步是为了导入到下一步的AI辅助编写。在设计文档中必须体现想要使用的接口、每一个接口之间的时序。例如,对于一个二值化的IP,在AXI-Lite接口设置阈值的时间可能在一帧图像的传输过程中间,那么这个时候是在图像传输完毕之后(或者下一帧图像传输之前)更新一个影子寄存器、还是直接使用新值,这都需要在文档中说明。完成文档设计之后,最好给IP的顶层连接写一个有接口信号定义的空模块,除非是一些开放性设计。

第三步,让AI自己写IP和cocotb测试。一定要说明白,要求参考上一步写的设计文档,顶层定义使用已经编写的IP顶层文件,仿真的时候不能只看cocotb的PASS,也要实际做波形观察和分析(如果是多模态的模型的话)。

基于cocotb的自动化测试

cocotb是一个Python库,本质上为测试代码提供了一个简化接口,但是并不代替Iverilog或者verilator的实际仿真功能。cocotb提供了完整的AXI接口测试模块与案例,可以快速构建基于AIX接口的IP测试。

在使用AI编写cocotb进行仿真的时候,可以遵循“预设路径测试-大规模数据测试-边界与错误数据测试”的方法。预设路径(或者也有叫Happy-path)测试是为了确定主要功能可以跑通、在理想情况(即输入数据没有出错)的时候该IP可以工作良好。大规模数据测试是为了验证在输入数据不出错的情况下IP还是可以工作良好。

边界与错误数据测试一般采用边缘条件或者错误数据输入的方法进行测试。比如在一个二值化IP中,输入一幅1x2大小的图像,查看其是否可以正确识别;或者输入两幅图像但是不提供第二幅图像的帧同步信号,观察IP的错误处理路径是否符合预期。又例如,一个IP需要先在AXI-Lite的寄存器中设置完成之后再传入数据,则测试代码可以尝试先传入数据再设置、或者设置两次之后再传入数据的时候,IP工作是否满足预期。对于错误数据处理的方法和过程应当也在IP设计文档中明确。

对于边界与错误数据测试的测试用例规划,分为两个大类。一类是顺序正确但是数据错误,另一类是数据正确但是顺序错误。对于顺序正确但是数据错误的测试,规划较为简单,再原有的操作顺序上,在不同阶段、不同数据注入敏感错误即可。对于数据正确但是顺序错误的测试,首先需要将低风险操作(比如CPU设置寄存器的先后顺序,这几个操作的先后顺序固化之后极低概率被打乱)先聚合成“原子操作”,该原子操作内部的顺序保持不变,但是原子操作之间的顺序可能发生变化,测试就是要将这些不按照总体操作顺序的原子操作打乱,看出错是否符合预期、出错之后是否能够自恢复或者复位,而不引起全系统的崩溃。

完场上述的约束,AI就明确知道开发和测试意图了,就可以指挥AI进行实际代码的编写。当然如果使用智力水平较高的AI,也可以只规划大方向,具体测试项和实现可以让AI自己规划并实现。

其他技巧

给IP插入一些版本与监测寄存器

AXI-Lite的地址空间中不能只有设置寄存器,最好是加上版本、Magic数、状态监测等寄存器。这里的重点在于IP状态监测,这可以使得CPU的驱动和业务代码可以获知当前IP处于一个什么状态、能否正常工作。最好是预留一个IP复位寄存器,如果IP进入了不可恢复错误的状态,CPU上面的代码可以获知这个错误状态并且直接对IP进行复位操作,而不需要进行整个FPGA的复位(代价太高、时间太长)。

测试用IP的编写

一般来说,测试用IP只需要从DDR的地址空间向待测IP搬数据就行了,数据生成和数据校验可以用CPU做。测试IP和驱动可以完全由AI编写,但是在编写的时候一定要保证测试IP与待测IP的接口对的上。

Linux内核驱动的修改与测试方法

对于一个定制器件的驱动程序,最好是可以独立成一个模块,在系统加载的时候同步加载。如果迫不得已要进行系统源代码的修改,一定要先进行QEMU启动测试之后再上板测试。QEMU可以下载特定版本的源代码自行编译(编译过程较为简单),修改后的内核配合根文件系统可以在QEMU上进行启动测试,或者配合已有的应用程序进行架构冒烟测试。

应用程序的开发测试方法

框架与底层原型开发

首先,一个可以长期维护的应用程序或者框架应当拥有良好的框架,这个框架需要开发者确定并且进行框架代码编写。另外,对于一些很底层的IO操作、寄存器操作,也需要开发者进行开发与调试,并且将原型代码调通,作为后续AI辅助开发的“地基”。

在原型开发的过程中,小模块可以直接由AI实现,但是必须规定好接口,最好不要在工程目录进行测试,而应该在树外充分测试之后再并入工程代码之中。比如,一个文件管理系统需要有一个AVL树模块,那么这个AVL树可以由AI自行编写并测试,开发者只需要规定好接口或者指示AI遵循某种编码规范即可,待AI开发与测试完毕之后在原型开发工程中直接调用该模块即可。

开发者需要完成的原型系统框架可以不是特别完善,但是一定要确保底层接口可用、底层过程清晰。这样AI才能在已有代码的基础上继续进行编写,否则很难跑通底层逻辑。框架性的东西可以体现在文档中,尤其是AGENTS文档。

单元测试

单元测试一般聚焦于单个模块的本地测试,比如软总线模块、日志模块等。单元测试首先需要进行单元功能文档的编写,文档中应当包括单元的功能、对于预期的输入输出描述等内容。如果对于输入操作顺序有要求的话,也要进行错误处理和错序操作相关的测试。相关思路可以参考基于cocotb的自动化测试章节。

系统集成测试

全系统测试是包含CPU应用程序、Linux内核驱动和FPGA的联合测试。一般来说,这三者应当在同一个工程中供AI随时能够查阅,否则几个系统之间的对接就会变得非常难搞。

系统集成测试除了参考基于cocotb的自动化测试章节的相关思路,还应该进行关键数据路径的人工校验。比如在一个DMA系统中,数据从AXI-Stream总线进入,并被送往DDR,然后CPU通过SGDMA读取DDR数据、或者进行P2P传输。这中间的数据路径可以通过插入ILA进行观测。在进行自动化测试的时候,可以人工设置ILA的相关触发信号,观察数据是否满足要求。再结合自动化测试给出的信息,基本上可以判定自动化测试的结果是否“真正”正确。某些数据路径可能无法进行观测,比如PCIe链路,这种情况可以将观测点设置到尽量近的地方,比如XDMA的AXI-MM接口上(一般也可以认为PCIe通路、XDMA是可信的,因为这都是已经有很多测试场景和应用案例的东西)。

posted @ 2026-09-29 15:20  LogicField  阅读(2)  评论(0)    收藏  举报