3. 算法加速需求分析与硬件映射
在把算法搬到 PolarFire FPGA 之前,最忌讳的动作是“先写 RTL,再想怎么接”。PolarFire 的逻辑规模、DSP 资源、LUT4 架构、片上存储(LSRAM/µSRAM)以及硬核接口(DDR、PCIe、SerDes)都是有限的,算法能不能加速、加速到什么程度、走哪条接口,取决于算法本身的四个特征:计算特征、数据流、并行度和存储访问模式。本节的任务就是把这四个特征量化,再映射到 PolarFire 的具体资源与接口约束上。
一、先看计算特征:算子类型决定资源去向
把算法拆成算子后,逐个判断它属于哪一类:
- 乘加密集型:卷积、矩阵乘、FIR、FFT 蝶形。这类算子应优先映射到 PolarFire 的 DSP 硬核(Math Block),每个 Math Block 含 18×18 乘法器和 48 位累加器,适合做定点的乘累加。
- 逻辑/位运算型:CRC、哈希、位域打包、LDPC 的异或网络。这类算子吃 LUT,应关注 LUT4 的级联深度和布线延迟。
- 查表/非线性型:Sigmoid、Tanh、激活函数、坐标旋转。适合用 LSRAM 做查找表,或分段线性近似。
- 控制/状态型:协议解析、状态机、调度。这类算子不适合并行展开,应放在控制路径,避免占用 DSP。
判断依据很直接:如果某个算子的乘加次数占总运算量的 70% 以上,它就是加速收益的主战场;如果它主要是分支和比较,加速收益有限,反而可能因为并行化而膨胀逻辑。
二、数据流:决定是流式还是块式
数据流描述数据在算子之间的传递方式,常见三种:
- 流式(Streaming):数据按顺序流过,算子之间用 FIFO 或握手信号连接。适合图像行处理、FIR、实时协议解析。优点是延迟低、存储需求小;缺点是难以做跨行、跨帧的全局操作。
- 块式(Block):先把一帧/一块数据写入片上缓存,再整体处理。适合 FFT、矩阵乘、二维卷积。优点是便于做转置和全局重排;缺点是需要 LSRAM 容量和带宽支撑。
- 混合式:局部流式、全局块式。例如图像先做行缓冲的 3×3 卷积,再按块做池化。
在 PolarFire 上,流式路径通常用 AXI4-Stream 或自定义 valid/ready 握手;块式路径则要规划 LSRAM 的读写端口和乒乓缓冲。数据流一旦确定,接口的位宽、时钟域和背压策略也就基本确定了。
三、并行度:从算法里“挖”出可并行的维度
并行度不是拍脑袋定的,要从算法的循环结构里找。以二维卷积为例,输出特征图有 H×W 个点,每个点做 K×K 次乘加。可并行的维度包括:
- 输出通道并行:同时算多个输出通道,每个通道一个 DSP 阵列。
- 输入通道并行:把多个输入通道的乘积累加树并行展开。
- 空间并行:同时算相邻的多个输出点,共享输入窗口。
并行度 P 与资源的关系可以粗略估算:DSP 用量 ≈ P × 每周期乘加数 / Math Block 每周期能力。PolarFire 的 Math Block 在 200 MHz 下每周期可完成一次 18×18 乘加,若目标算力是 50 GMAC/s,则至少需要 250 个 Math Block 在 200 MHz 下满负荷。实际还要留出 30% 余量给控制和流水线气泡。
并行度还受存储带宽约束。若每个周期要喂 P 个乘加,输入数据带宽就是 P × 数据位宽 × 时钟频率。例如 P=16、16 bit、200 MHz,则输入带宽约 51.2 Gbit/s,这已经接近单条 DDR4 通道的可用带宽,必须用片上缓存或宽总线来缓解。
四、存储访问模式:决定缓存架构和接口选择
存储访问模式是 PolarFire 映射中最容易翻车的地方。要问三个问题:
- 访问粒度:是连续突发,还是随机小颗粒?连续突发适合 DDR 和 AXI Burst;随机小颗粒适合片上 LSRAM 或带缓存的访问。
- 复用距离:同一个数据在被丢弃前会被复用多少次?复用距离短,用行缓冲/窗口寄存器;复用距离长,用 LSRAM 块缓存。
- 读写比例与冲突:是否存在读写同一块存储的冲突?若有,需要双端口 LSRAM 或乒乓缓冲。
例如,3×3 卷积的输入窗口在行方向复用 3 次、列方向复用 3 次,复用距离短,用行缓冲即可;而 FFT 的旋转因子需要按蝶形级数反复读取,复用距离长,应放在 LSRAM 中并做地址重排。
五、映射到 PolarFire:加速路径与接口约束
把上述四个特征汇总,可以得到一张映射决策图。下图展示了从算法特征到 PolarFire 资源与接口的对应关系,以及关键约束的检查点。
图中左侧是算法特征,中间是 PolarFire 可用的加速资源,右侧是必须检查的接口与资源约束。箭头表示映射方向,底部虚线表示当约束不满足时需要回退调整并行度或数据流。以 3×3 卷积为例:若并行度 P=16、数据位宽 16 bit、时钟 200 MHz,则输入带宽约 51.2 Gbit/s,DSP 需求约 250 个 Math Block,同时需要 LSRAM 做行缓冲,DDR 侧要用 AXI Burst 保证突发效率。这些数字是教学示例估算,实际工程中必须用 Libero 的综合报告和时序报告核对。
六、接口约束的落地检查
在 PolarFire 上,接口约束不是抽象概念,而是具体到引脚、时钟和协议:
- DDR 接口:PolarFire 的 DDR 控制器支持 AXI4,突发长度和位宽决定有效带宽。若算法需要 51.2 Gbit/s,单通道 DDR4-2400 理论带宽 19.2 GB/s,实际可用约 60%~70%,即 11.5~13.4 GB/s,约 92~107 Gbit/s,单通道可以满足;但若并行度再翻倍,就需要考虑多通道或提高片上缓存命中率。
- PCIe 接口:若算法作为加速卡与主机交互,PCIe Gen2 x4 理论 20 Gbit/s,实际约 12~14 Gbit/s。此时算法输入输出必须做分块和流水,避免一次性搬运整帧。
- SerDes:用于板间或传感器直连,注意参考时钟、均衡和协议层封装。
- AXI4-Stream:流式路径的首选,注意 valid/ready 握手和背压。若下游不能持续接收,上游必须能暂停,否则数据丢失。
总结来说,算法加速需求分析的核心是把“算法想做什么”翻译成“PolarFire 能做什么”。计算特征决定资源类型,数据流决定缓存架构,并行度决定资源用量,存储访问模式决定接口和带宽。四者相互制约,任何一项超出约束,都要回到上一层重新调整。只有把这四个特征量化清楚,后续的 RTL 实现和性能评估才有可靠的起点。