高层次综合 (HLS)
硬件设计与处理近几年来发展迅速。 过去我们的电路相对简单,硬件设计师们可以很方便的画出每一个晶体管,规划他们的连接方式,甚至他们的板上位置。可以说所有工作都是人工完成的。但随着越来越多晶体管的设计需要,硬件工程师也越来越需要依赖自动化设计工具来帮助他们完成设计,而这些设计工具也相对应的变得越来越精密。工程师在这些设计工具的协助下也更具效率。他们不再具体操作每一个晶体管,而只需要设计数字电路,电子设计自动化工具(EDA)把这些抽象而概括的电路自动转换成实际的部件构造版图。
米德和康威(Mead&Conway)的方法,也就是使用一种硬件描述语言(Verilog, VHDL),并把其编译成片上设计的方法在上世纪 80 年代开始广为使用。但这之后硬件的复杂度还在以指数函数的增长速度发展,硬件工程师们只好寻求更加概括而高层次的编程语言,RTL 应运而生。在 RTL 里,设计师不需要考虑怎么构造一个寄存器或怎样安置这些寄存器,而只需要考虑这些寄存器在设计中起到怎样的作用。EDA 工具可以先把 RTL 转化成数电模型,再由模型转换成一个设备上的具体电路实施方案。这些"方案"对器件的制造来说必不可少,可以用于规定某个自定义设备,也可以用于编程一些现有的设备,比如 FPGA。如我们现在所见,新的设计方法确实帮助工程师们的设计思路变得更加清晰。更多关于这方面的探讨参考注释。
HLS 则是在这基础上更高层的一种方法,设计师们在 HLS 下需要更多的考虑大的架构而非某个单独部件或逐周期运行。设计师在 HLS 下需要注重的是系统的运行模式,HLS 工具会负责产生具体的 RTL 微结构。最早大多数 HLS 工具是基于 Verilog 的,用户需要使用 Verilog 语言进行描述,工具也通过 Verilog 产生 RTL。现如今很多 HLS 工具开始使用 C/C++作为设计师端的语言。当然,选择 HLS 工具最重要的还是看它能否综合我们需要的程序,而不是它使用什么语言。
总体来说,HLS 可以自动完成以下曾经需要手动完成的工作:
HLS 自动分析并利用一个算法中潜在的并发性
HLS 自动在需要的路径上插入寄存器,并自动选择最理想的时钟
HLS 自动产生控制数据在一个路径上出入方向的逻辑
HLS 自动完成设计的部分与系统中其他部分的接口
HLS 自动映射数据到储存单位以平衡资源使用与带宽
HLS 自动将程序中计算的部分对应到逻辑单位,在实现等效计算的前提下自动选取最有效的实施方式
HLS 的目标是根据用户提供的输入和限制自动替用户做出很多决定。每个 HLS 工具在实际施行的效率上相差甚远,这其中我们有一些非常不错的选择,例如赛灵思 Vivado HLS, LegUp, Mentor Catapult HLS。他们出众的特性在于可以支持更多更广泛的程序转换。我们在本书中将使用 Vivado HLS 作为演示软件,但是设计的思路与技巧在各个软件中应当是通用的,读者只需要在各自的软件中对语法进行稍微的调整。
大多数 HLS 工具需要用户提供功能的规范,交互的描述,一个对接的计算设备,和目标优化方向。而对于 Vivado HLS 来说,用户需要:
一个用 C/C++/System C 编写的函数
一个测试平台用于验证结果
一个 FPGA 开发版
期望的时钟周期
一个简单的实施指导
HLS 工具没有强大到可以处理任何代码。很多我们平时在软件编程中常用的概念在硬件实施中很难实现,所以硬件描述语言对于具体实施会更加灵活。通常这些 HLS 工具需要用户提供一些附加信息(通过 suggestion 或 #pagma)来帮助完善程序,因此我们说 HLS 工具会同时"限制"又"加强"了一门语言。举例而言,HLS 工具一般无法处理动态内存分配,大部分工具对标准库的支持也非常有限。用户也应当避免系统调用和递归以尽量降低复杂程度。除去这些设计限制之外,HLS 工具的处理范围非常的广(包括直接内存访问,流,片上内存),优化效率也很高。
根据 Vivado HLS 的使用指南,我们将对我们的输入程序作出以下规范:
不使用动态内存分配(不使用 malloc(),free(),new 和 delete())
减少使用指针对指针的操作
不使用系统调用(例如 abort(),exit(),printf()),我们可以在其他代码例如测试平台上使用这些指令,但是综合的时候这些指令会被无视(或直接删掉)
减少使用其他标准库里的内容(支持 math.h 里常用的内容,但还是有一些不兼容)
减少使用 C++中的函数指针和虚拟函数
不使用递归方程
精准的表达我们的交互接口
当 RTL 级的设计可用时,大多数 HLS 工具会进行标准 RTL 设计流。而在赛灵思 Xilinx Vivado 设计套装里进行的是逻辑综合,将 RTL 级设计转换成一个 FPGA 逻辑部件的连线表,这份连线表不仅包含需要的逻辑部件还包含他们的连接方式。Vivado 之后将连线表和目标设备中的可用资源相关联,这个过程被称作布局及布线(PAR)。产出的 FPGA 配置被附在比特流(bitstream)上,用户可以将比特流上传到 FPGA 以实现想要的功能。比特流实质上是用二进制表示 FPGA 上每一个可用资源的配置,包括逻辑部件的使用,连线的方式,和片上的内存。大型 FPGA 例如赛灵思 UltraScale FPGA 拥有超过十亿个可配置比特,较小的 FPGA 上也至少有几亿个可配置比特[64]。
评论