Parallel Programming for FPGAs 介绍 阅读笔记

554 阅读6分钟

from:FPGA并行编程

HLS自动化能力

  • 算法:自动分析并利用一个算法中潜在的并发性
  • 时钟路径:自动在需要的路径上插入寄存器,并自动选择最理想的时钟
  • 数据方向:自动产生控制数据在一个路径上出入方向的逻辑
  • 接口:自动完成设计的部分与系统中其他部分的接口
  • 数据映射:自动映射数据到储存单位以平衡资源使用与带宽
  • 逻辑映射:自动将程序中计算的部分对应到逻辑单位,在实现等效计算的前提下自动选取最有效的实施方式

HLS编程限制

  • 内存:不使用动态内存分配(不使用malloc(),free(),new和delete())
  • 指针:
    • 减少使用指针对指针的操作
    • 减少使用C++中的函数指针和虚拟函数
  • 调用:
    • 不使用系统调用(例如abort(),exit(),printf()),我们可以在其他代码例如测试平台上使用这些指令,但是综合的时候这些指令会被无视(或直接删掉)
    • 减少使用其他标准库里的内容(支持math.h里常用的内容,但还是有一些不兼容)
  • 逻辑:不使用递归方程
  • 接口:精准的表达我们的交互接口

FPGA构造

  • 查找表(LUT):把地址信号输入进去,对应内存位置的内容会直接被输出出来。
    • 一个N位查找表可以以一个N位输入真值表的方式来表示。
    • 一个2位输入查找表,共有2^2比特。

PS:实际中的FPGA大多使用4-6位输入的查找表作为运算基础,一些大型FPGA内甚至有几百万个这一级别的查找表。

  • 可配置逻辑块(CLB)或逻辑矩阵块(LAB)。有些设计工具中还会把它称作片(Slice)。
    • 触发器(FF)是FPGA最基本的内存单位,通常触发器是配有查找表的,这样是为方便查找表之间的复制与组合。
    • 函数逻辑

  • 连线通道和开关盒:可编写的互联是FPGA最关键的特性之一

  • IO模块
    • 微控制器(通过AXI接口连接片上ARM处理器 )
    • 传感器(通过A/D接口连接天线)
    • 作动器(通过D/A接口连接电机)etc

  • 块RAM(BRAM):支持多种内存形式和接口的可配置随机储存器。
    • 芯片上各部分的数据转移
    • 储存大一些的数据集

可以把这些数据传给本地片上总线(与可编程逻辑交流)或处理器总线(与片上处理器交流)等接口。

可以储存字节,对字,全字,双字等。

属性 外部内存 BRAM 触发器
数量 1-4 几千 几百万
单个大小 GB级 KB级 bit级
总量 GB级 MB级 100KB级
宽度 8-64 1-16 1
总带宽 GB每秒 TB每秒 100TB每秒
容量配置
- 拆分:32000 x 1比特,16000 x 2比特,8000 x 4比特等形式存在。
- 串联:形成更大容量
设计使用:
- BRAM想成一个寄存器堆,它可以直接输出到一个自定义的数据路径(DSP48),可以与处理器交流;
- 也可以像可编程逻辑上的数据路径传输数据。

FPGA设计与处理

设想中的嵌入式FPGA设计结构图,包括接口核心(蓝色框),标准核(绿色框),和应用加速核(紫色框)。注意应用加速核也可能自带流接口,内存对应接口。

  • I/O接口核:通常以RTL的形式构架并需要加上其他的时序限制

整个设计的外围临近I/O引脚的地方通常是一些少量的逻辑,它们一般用来完成关键时序和协议,比如内存控制模块,视频接口核心或模拟数字转换器。

  • 标准核
    • 处理器核心
    • 片上内存核连接开关
    • 原生的函数处理部件:滤波器,FFT,编解码器,etc

PS:标准核心主要是同步电路,它除了时钟时序限制之外不大有限制。这些特点让标准核更容易在不同FPGA中兼容,当然,被转移到另一种FPGA结构中时还是需要一定优化的。

  • 加速器核:同标准核一样,加速核通常是由时钟限制而规定的同步电路,但这些核却是系统设计师们在具体应用中不可避免要接触的部分。
    • 使用:
      • 以核为基础的设计方法:用HLS创造出这种核之后把他们与IO接口核和标准核组合到一起(可以通过Vivado IP Inegrator这样的软件)
      • 以平台为基础的设计方法:设计师先用IO接口核和标准核组合出一个样板,然后再用HLS通过壳(shell)的接口将各式算法或对象组合进去。只要壳支持双边的接口,加速器核在平台与平台之间的移动也非常容易。

设计优化

衡量标准

我们用任务(task)这个术语来表示一个行为的基本单位,用户可以在Vivado HLS中发现与之对应的是调用函数。

两种不同设计的任务间隔和任务延迟,上方的弧线指示的是任务间隔,下方的弧线指示的是任务延迟。左右两个设计的区别在于,左边是流水线(pipeline),右边使用了更顺序化的设计。

设计空间与限制
  • 空间

HLS的一个特点就是在决定结构上的一些此消彼长的设计时,不再需要考虑让它适用于指令集的结构限制。在HLS设计中,设计出一个在同周期内执行成百上千个RISC级指令外加几百个周期程度流水的系统是非常常见的。

  • 限制

HLS设计师需要考虑流水,内存排布,I/O接口

流水举例:

顺序化的结构很难解析码流,主要出于控制逻辑的复杂度。另外,控制逻辑负责规定任务延迟和任务间隔。顺序化结构的性能有时取决于处理的数据。

Vivado HLS可以产出更加流水,平行,性能上也更好的结构。其中之一叫做函数流水。函数流水结构是把函数内所有的代码都当作计算数据路径的一部分,再加上少量的控制逻辑。*循环和分支被转换成无限制的结构。*这种结构特点分明,容易分析,一般用于处理连续而简单的高码率数据。

限制举例:

  • 递归(recurrence),这里是指某个部件的计算需要这个部件之前一轮计算的结果
  • 资源限制
    • 硬件

      如果 int32_t f(int32_t x)这样形式的函数作为一个单独模块在100MHz的频率和1的任务间隔下运行,它最大的数据处理量就是3.2G比特。

    • 用户设置

      如果用户规定了在综合中可用的操作数,这其实是给处理率添加了限制条件。

优化策略:重构代码