FPGA Xilinx Zynq 系列(二十六)高层综合

2020-12-30 11:12:27 浏览数 (1)

大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。

今天给大侠带来FPGA Xilinx Zynq 系列第二十六篇,开启十四章,讲述高层综合等相关内容,本篇内容目录简介如下:

14. 高层综合

14.1 高层综合的概念

14.1.1 什么是高层综合 (HLS)?

14.1.2 高层综合的动机

14.1.3 设计指标和硬件架构

14.2 HLS 工具的开发

14.3 HLS 源代码语言

14.3.1 C语言

14.3.2 C

14.3.3 system C

14.3.4 用于高层综合的其他语言

14.4 介绍 Vivado HLS

14.4.1 Vivado HLS 做什么?

14.4.2 Vivado HLS 设计流

14.4.3 C 功能性验证和 C/RTL 协同仿真

14.4.4 实现的度量指标和考虑因素

14.4.5 高层综合过程的概述

14.4.6 解决方案:探索设计空间

14.4.7 Vivado HLS 库的支持

14.5 在 Zynq 设计流中的 HLS

14.6 本章回顾

14.7 参考文献

本系列分享来源于《The Zynq Book》,Louise H. Crockett, Ross A. Elliot,Martin A. Enderwitz, Robert W. Stewart. L. H. Crockett, R. A. Elliot, M. A. Enderwitz and R. W. Stewart, The Zynq Book: Embedded Processing with the ARM Cortex-A9 on the Xilinx Zynq-7000 All Programmable SoC, First Edition, Strathclyde Academic Media, 2016。

高层综合

在数字系统设计中,一个明显的趋势是要加速开发的周期,关键是还不会牺牲验证过程。这不可避免是由商业因素,特别是尽快把新产品推向市场的需求所驱动的。当然,一些针对在设计工作中降低开发成本的方案也是非常具有吸引力的。

支撑设计加速策略的概念,是(一)设计重用和(二)抽象层级的提升。这两者在本书都已经介绍过了,这里我们要特别关注于后者,聚焦于 Xilinx Vivado High Level Synthesis (即 Vivado HLS,高层综合)。这个工具直接使用 C、C 或 SystemC 开发的高层描述来综合数字硬件,这样就不再需要人工做出用于硬件的设计,像是 VHDL 或 Verilog 这样的文件,而是由 HLS 工具来做这个事情。HLS 的本质,就是让所设计的功能和它的硬件实现是分离的 — 基于 C 的描述并不会决定硬件架构,继而在 RTL 级别的设计上也是如此 — 这带来了巨大的灵活性。

我们会看到,由于提升了抽象的层级,基于 C 的语言有可能极大地减少设计时间。而且,HLS 过程实现了一种集成了的机制来在不同的硬件实现上做生成和评估,这样就易于发现最佳的架构。

本章接下来会定义和找出 HLS 的需求,同时也会简单回顾发展历史和所用的语言。会介绍 Vivado HLS 工具,以及从宏观的角度来看 HLS 设计流和过程。接下去在 第 15 章会有一个更深入的对 Vivado HLS 的研究。

14.1 高层综合的概念

在第 15 章讨论 Vivado HLS 工具和实际的设计方法之前,关键要建立起一些内在运作的基本概念。我们从一些最基本的问题开始!

14.1.1 什么是高层综合 (HLS)?

应该先对高层综合有一个清晰的定义,为此我们必须首先回顾针对 FPGA 的数字设计的抽象的概念。

和许多其他领域类似,抽象的意思是 “ 撤走 ”。其实就是对细节的隐藏 —— 抽象的层级越高,所隐藏的细节就越多。文献中提出过各种抽象的模型,很多都是从 Gajsku 和 Kuhn 用于超大规模集成电路(Very Large Scale Integration,VLSI) 设计 [9] 的 “Y-chart” 发展而来的,那篇文献发表于很多年前的 1983 年!不过,这里我们只关注于当前的 FPGA 设计实践,认为存在着四种抽象层级,自底向上依次为:结构性的、RTL、行为性的和高层,如图 14.1 所示:

图 14.1: FPGA 设计中的抽象层级

从用像是 VHDL 或 Verilog 这样的 HDL 做的设计项的角度来说,最底层的抽象 (结构性的)涉及到直接的实例化、配置和连接组成设计的每个硬件单元。这甚至可能会向下扩展到 LUT 和 FF 的层次。这个风格下,设计者可以直接控制所有的设计细节,因而综合过程对设计的优化就不太能做了。更常见的情况,设计者在 “ 寄存器转移层(Register Transfer Level,RTL)” 做设计。这个层级的抽象隐藏了技 术层级的细节,但还是表现为从寄存器和寄存器之间发生的可以被解释执行的操作的角度来描述的设计。

有一些逻辑综合工具是被设计出来用于这个抽象层级的,比如用于把 RTL 代码转换到硬件。行为性的 HDL 描述是在比 RTL 更高的抽象层次上,并且构成对电路的算法描述 (也就是如何 “ 行为 ”),而不是描述每个寄存器的操作的表达。因此,行为性的 HDL 的使用,更加强调了综合工具根据描述生成硬件的能力。设计者会由此而失去了对最终实现的某些控制,但是能由于更快速地创建设计而受益。最后,本章要讨论的高层设计项方法并非实际从 HDL 中导出,而是使用适合在抽象的算法层级上表达设计的语言,也就是 C、C 、和 SystemC。这些语言,实际上通常作为对系统建模的高层的第一步,用于开发系统级模型 (SystemLevel Models,SLM)[22]。

在上面的讨论中,我们在 HLD 的一些略有不同的情境下都用了 “ 综合 ” 这个术语。高层综合和其他类型的综合是不同的。在 FPGA 设计中,“ 综合 ” 通常指的是逻辑综合,也就是分析和解释 HDL 代码并形成对应的网络表的过程。高层综合实际上是把高层的 C、C 或 SystemC 的代码综合成 HDL 描述,然后可以用下层的逻辑综合来获得网络表。换句话说,在把 Vivado HLS 设计发展成硬件实现的过程中,高 层综合和逻辑综合都被用上了 (一个接一个),如图 14.2 所示。

进一步的,物理综合指的是把 HDL 根据目标 FPGA 的实际知识转换成网络表,从而能针对芯片的物理特性和可用的资源来做设计优化。

14.1.2 高层综合的动机

用高层表达来抽象低层细节,也就意味着电路的描述变得简单了。这个方法不能真的免除对诸如字长、并行性和共享这样的特性的需求,但是从大的方面来说,设计者指导设计的过程,而工具负责实现细节。结果是设计能比需要直接描述所有的特性的传统方法更为迅速地产生出来。重要的是,HLS 中做到的功能和实现的分离意味着源码和架构之间不是绑定的。架构的变化可以快速地在 HLS 过程中施加进去,而不需要在源码上作基础性的重新工作,而 RTL 层级的设计时就必须做这样的重新工作。

图 14.2: 高层综合和逻辑综合

当然,放弃完全控制的实现,需要设计者信任由 HLS 工具实现底层功能的正确性和高效性,而且理解如何能对这个过程施加影响。当然,绝对有显著的理由要这样做,因为这能在相当程度上加速设计的过程。

从更实际的层面上来说,用软件语言来做的高层综合对很多设计者来说都更方便,因为这些语言广泛适用于开发算法和写系统层面的说明。因此能利用很多工程师所习惯的 C、C 和其他编程语言的经验来做 FPGA 的设计。于是把软件快速转换成硬件设计语言的能力—— 关键的是,不需要创建然后验证等价的针对硬件的设计—— 实现了设计过程的简化 [22]。从软件描述到硬件设计的转换,通常会强调开发HDL 和做验证这些设计步骤与基于软件的参考设计之间的不同。而用这个方法,两个过程可以合并为一个。HLS 从系统开发和软件 / 硬件划分中也能受益,因为面对系统的两个部分就有了共同的语言,这样就能使得对设计的组成部分做调整、做重新部署都变得容易,因为这些都是一起迭代完成的。

随后会详细说明的是,高层综合工具中所表现出来的自动化,让设计者能快速地做出指定设计的不同版本来。比如,同一个设计可以做出不同程度的并行性来,这样可以探索不同的设计空间,评估各种权衡的结果,找出最佳的解决方案来。

总的来说,如果必须用一个单词来解释为什么要做 HLS,那就是 “ 生产力 ”!

14.1.3 设计指标和硬件架构

本章之前着重指出的一个重点,就是在 HLS 里,功能性的描述和实现是分离的。因此,设计者有机会评估 HLS 过程产生的各种可能的架构,根据他 / 她的需求来做优化。不过,这个事情就带出了一个问题:“ 设计者想要优化的是什么?”

简单来说,硬件设计有两个基础性的指标:

  • 面积,或者说资源成本 — 用来实现所期望的功能所需要的硬件的数量;
  • 速度 , 或者具体来说是吞吐率 — 电路能处理数据的速率。

还有其他的因素,有的时候这些因素之间的关系是微妙的 (在 14.4.4 节有深 入的探索),但是这些是其中两个最重要的。

设计者总是要面对面积(资源成本)和吞吐率之间的权衡,这也是在 HLS 过程 中要评估和优化的关键方面。系统可能会实现出某个最小的吞吐率或最大面积,因此要做的事情是针对特定的问题做出最佳的决策。HLS能快速帮助设计者做到这点。

我们可以用装修房子来打个比方,假设说整个房子要装修。这个活儿可以由一 个油漆工来做,他 / 她要花 6 个星期。而 6 个油漆工可以用 1 个星期做完,或者说3 个油漆工用两个星期,以此类推。不同的 “ 方案 ” 需要在资源(油漆工的数量)和吞吐率(完成工作所需的时间的接受程度)之间做出权衡。组织地不好的活儿可能是要 5 个油漆工花 4 个星期来完成房子的装修,这当然是一个糟糕的方案!

硬件架构的实现也是类似的。在较高的抽象层级上,功能性的实现是以处理器 资源来计算的。使用更多的单元能让处理完成得更快 (高成本并且高吞吐率),而在这个尺度的另一端,可以只使用单个处理器资源进行不断重用(低成本并且低吞吐率)。在这样的权衡中还能找到几个平衡点。当然,和装修的例子一样,也可能会出现糟糕的设计,以很高的成本实现很低的吞吐率。

图 14.3 给出了成本 / 吞吐率权衡的一个简单图示。

图 14.3: 用 HLS 做设计权衡的概念性表示

14.2 HLS 工具的开发

高层综合不是新概念,尽管受到大量的研究关注,在业界也有一定程度的使用,但是它还没有成为 FPGA 设计者广泛接受的新宠 [12][34]。不过,随着最近 HLS的软件设计工具的发展,以及之前说过的对 HLS 的显著的需求,因此无需惊讶对于HLS 的兴趣是在增长的 [21]。

值得指出的是,当代的 HLS,就动机、框架和术语而言,与 [20] 中描述的早期方法是非常相似的,特别是运算的调度和绑定 (后面详细解释),以及用一个描述来产生多个设计版本的能力。在那篇论文写作的年代 (1990 年代早期),还有各种没有解决的问题,包括验证、人工干预 / 指导、处理复杂的约束以及 HLS 产生设计的集成。设计项的方法包括了像 Pascal 和 Ada 那样的编程语言 [29]。C 语言后来成为了主流,实际上直到现在 C 语言还是用于 HLS 的最流行的语言。

后来,用面向对象的编程语言来做硬件描述的兴趣日益浓厚,一开始是 C , 后来 Java 也略有涉及 [8][9][28]。对于更精密的硬件设计,面向对象软件实现了所需的抽象机制。SystemC 里带有专门用于硬件设计的深入的语言特性,比如能做模型层次体系、位精确和硬件的并行执行行为的描述 [10][25]。SystemC 已经成为系统层级做复杂建模设计的主流。

有不少其他语言都乐意地拿 C 语言来做了一定程度的改造,包括 Handel-c、Cto-Silicon Compiler 和 Impulse-C。Handel-C 最初是一家英国公司 Celoxica 做 的,后来被 Mentor Graphics[24] 收购了;C-to-Silicon Compiler 是 Cadence 的 [7] ;而 Impulse-C 是 Impulse Accelerated Technologies 开发的 [15]。所有这些 语言都提供了做高层设计项的方法,但是与我们对 HLS 的定义(也就是功能和架构的分离)的契合的程度是不同的。所有的语言都在算法和做 FPGA 和 Zynq 开发所需的 FPGA 系统设计工具之外,提供了额外的专业的工具。

另一方面,在21世纪初,有几篇论文是关于基于MATLAB的设计方法的[2][13], 然后从那时起成为 AccelDSP (现在已经过时的 Xilinx ISE 套件的一部分)的一个 功能,它能部分综合高层 MATLAB DSP 函数 [31]。现在,从 MATLAB 代码和 Simulink 模型做综合已经成为 MathWork 自己的 HDL Coder 产品的主要功能,实现了非常丰富的 MATLAB 到 RTL 的转换能力 [23]。从 MATLAB 代码做综合的吸引力,和从 C 代码做综合的动机是相似的:高层设计方法可以用来做设计,就抽象走了很多实现的细节。特别是,作为 Xilinx System Generator 的内部平台,许多 FPGA 设计者也许已经熟悉 MATLAB 编程和 MATLAB 的环境了。

回到本章的主题,Xilinx 的 Vivado HLS 工具原本是加州大学洛杉矶分校出来的 AutoESL Design Technologies 公司开发的 AutoPilot。在市场了寻找了一圈最好的可用的 HLS 技术之后,Xilinx 在 2011 年初收购了 AutoESL Design Technologies[3][4][30]。Xilinx 后来把 AutoESL 集成进了 ISE Design Suite,以 及后来的 Vivado Design Suite,那时候开始改名叫做 Vivado HLS[27]。

这样的发展历程是相当重要的,它标识着 HLS 已经从一个简陋的工具成长为主流的开发工具了。

14.3 HLS 源代码语言

接下来,我们要开始详细讨论 Vivado HLS 工具,不过首先,我们先来看看总体上 HLS 用的源代码语言的情况。我们先来看三种 Vivado HLS 中用的三种语言的背景情况,就是 C、C 和 SystemC,然后简单总结一下第三方软件开发工具支持的其他语言。

14.3.1 C语言

那个流行的通用的 C 语言,是一种过程型的编程语言,最初是由贝尔实验室开放,从 1970 年代一直使用至今 [18][26]。1989 年由美国全国标准组织 (AmericanNational Standards Institute,ANSI)做了标准化,后来被国际标准化组织 (International Organization for Standardization,ISO)接纳为 ISO 9899 标 准。从那之后出现过几个不同的修订版本,使其在语言中加入了一些新的特征,最新的是 2011 年版 [16]。C 语言的标准化版本可能被叫做 “ANSI-C”、“ISO-C” 或直接就叫 “ 标准 C”。

在历史上,C 代表了软件编程中抽象层级的提升:它让程序可以用更高级的结构和命令来写,而不是汇编语言。这曾经代表了简化编程工作的极大的先进性:所需的代码行数更少,从而潜在的错误就更少,能做更快的调试和验证过程。因为能用在不同的平台上,它也能让代码便携性更强。

汇编语言需要花更多的设计努力,但是给了设计者完全、直接的控制,因此, 为了让 C 语言能成功,它还得足够高效来取代汇编语言。某种程度上,C 的发展和HLS 做硬件的概念是类似的 —— 两种设计都是在更高的层级上的抽象,好处包括减少开发时间和代价、易于验证,并提高了便携性。

在定义了核心功能的标准 C 之外,C 可以扩展,加入面向应用和目标平台的库。比如,在用 C 来开发运行在 Zynq 的 ARM 上的软件的时候,就需要 SDK 里的额外的库来支持浮点和定点运算,也有用于 NEON 处理器的库。

C 和其他编程语言有千丝万缕的关系,关系最密切的是 C 。

14.3.2 C

C 是一个基于 C 的面向对象语言,它在 C 的基础上扩展了类、模板、多态和虚函数的概念,还有一些其他的特性。C 的抽象层次总的来说比 C 要高,因为 C 具有一些特性能隐藏细节,能做更精密、灵活的代码开发。另一方面来说,C 的语言特性和编程风格和 C 是兼容的,因此 C 可以认为是 C 的扩展集。总的来说,C 是比 C 更高级的语言,但是仍保留对低层 C 程序的支持。

和 C 一样,C 也是贝尔实验室做出来的。C 的标准最初是 1998 年作为 ISO 14882 出版的,并且经过修订出版了一些后续版本,最新的是 2011 年版 [17]。

14.3.3 system C

虽然这里我们把 SystemC 当作一种独立的语言,但是严格来说它是 C 的一种 扩展,也就是在开发项目中引入相应的头文件 “systemc.h” 作为专门的类库。SystemC 能以 C 风格的代码来实现 HDL 的以硬件为中心的概念,比如层次结构、并行和周期精确,这些都无法以标准 C 的形式来表达。

在 SoC 中,SystemC 常用于会话级建模(Transaction Level Modelling,TLM) 和电路系统级 (Electronic System-Level,ESL)设计中 [5]。TLM 是很高层的描述方式,它对系统的部件之间的交互做建模,而 ESL 是在很高的抽象层级,就是针对功能性和基础架构做系统设计。也就是说这两个方法都是在开始做每个部件的功能性实现之前,做 SoC 高层框架的开发和精调的。在 TLM 中,各种层级的抽象都是可能的,比如,就每个部件的实现目标,和系统会话有关的时序准确度 [6]。这个语言也能在开发过程中作为集成了的一部分,用于 ESL 验证 [11]。

SystemC 早期的工作是由 Open SystemC Initiative 组织支持的 (这个机构 2011 年与电子设计自动化(Electronic Design Automation,EDA)组织 Accellera 合并,成为 Accellera Systems Initiative[1])。那是 SystemC 的起步阶段,IEEE 在 2005 年把 SystemC 的标准接纳为 IEEE 1666,后来修订为 IEEE 1666-2011[14]。另外这个标准也接近支持模拟和混合信号的 SystemC AMS。

已经在 TLM 和系统工程中使用 SystemC 的用户特别适合用这个语言来做 HLS, 不过就算没有那样的背景,设计者们也会发现 SystemC 的面向硬件的特性使得这个语言非常适合来做 HLS,特别是用来开发复杂的系统。

本章的篇幅无法深度介绍 SystemC,而是主要用 C 语言来作说明例子。读者可以参考 [5] 和 [14] 来获得 SystemC 的进一步的资料。

14.3.4 用于高层综合的其他语言

在 14.2 中概述过,用做 HLS 的语言大部分都是基于 C 的,包括在 Vivado HLS 中支持的 C、C 和 SystemC。我们也指出第三方 HLS 设计流包括了其他基于 C 的语言,比如 HandelC,以及 MATLAB 代码。对 HLS 的研究的兴趣仍在继续,将来还有可能出现更高级的支持 FPGA 综合的语言。

14.4 介绍 Vivado HLS

本节从定义 Vivado HLS 做什么和怎么做开始,然后再来考虑它在 Zynq 设计流中的地位。后面的第 15 章会涉及工具的实际使用,并深入讨论算法、接口综合以及在创建和评估解决方案时所用到的过程。

14.4.1 Vivado HLS 做什么?

简单来说,Vivado HLS 把 C、C 或 SystemC 的设计转换成 RTL 实现,然后就 可以在 Xilinx FPGA 或 Zynq 芯片的可编程逻辑中综合并实现了 [33]。这代表了第 258 页上的图 14.2 中所描绘的高层综合步骤。

需要着重指出的是,在 HLS 中,所有基于 C 的设计都是要在可编程逻辑中实现 的,也就是说和要运行在处理器(就是 Zynq 的 ARM 处理器或是 MicroBlaze 这样的软处理器)上的软件代码是截然不同的。

在做 HLS 的时候,要分析设计的两个主要方面:

  • 设计的接口,也就是它的顶层连接,以及;
  • 设计的功能性,也就是它所实现的算法。

在 Vivado HLS 设计中,功能性是从输入的代码中,经过算法综合(Algorithm Synthesis)的过程来综合的。接口可以通过以下两种方式的其中一种被建立:(一)可以是人工指定的,(二)也可以是从代码中推导出来的 (Interface Synthesis,接口综合)。图 14.4 给出了一个简单的概念性的图(注意这个图中只有部分接口类型)。

如果采用 SystemC 作为输入语言,接口是必须人工指定的,只有两种情况例外, 后面会提到 [33]。

图 14.4: 算法和接口的说明,显示了部分接口类型

算法综合

算法综合关注的是设计的功能性。所期望的行为,是将输入传递给过程(输入给 HLS 过程的是用所选的编程语言写的一个函数)的 C、C 或 SystemC 代码所阐述的。从代码中推出运算,然后转换成一组 RTL 语句,通常这组语句需要几个时钟周期来执行。

后面还会讨论到,设计者可以通过 Vivado HLS 指令来控制算法综合的过程,在 HLS 所产生的 RTL 输出中加入一些变化。比如,方案 1 可能需要 500 个 slice 来实现,需要 20 个时钟周期来执行,而方案 2 可能需要 1200 个 slice,执行需要 10 个时钟周期。设计者能做实验,按照自己要实现的指标来找到的所需的结果。

接口 I:接口综合

顾名思义,接口综合指的是 HLS 设计中的接口的综合,这既是指端口,也是指所用的协议。所有端口的细节 (就是类型、尺寸和方向)是从 C/C 文件中的顶层函数的参数和返回值里推断出来的;而协议是从端口的表现推断出来的。比如,最简单的接口可以是一条 1 比特的线,而更复杂的接口,可能要用总线或 RAM 接口。自然,综合出来的接口能顺畅地与系统中的其他模块通信。

能从接口综合中推断出来的接口包括:线、寄存器、单向和双向握手、FIFO、 存储器和总线 [33]。还有一些和接口综合相关的选项,特别是可以从全局变量中推断出端口,还能加入全局时钟使能。在第 15 章会详细讨论接口综合。

接口 II:人工指定

接口综合完全支持 C 和 C 设计,但是不能支持 SystemC,因此,SystemC 设计 的接口必须人工指定,接口的行为需要完整描述。这涉及到 SystemC 语言的硬件描述特性,第 15 章会用一个例子来说明基于 SystemC 的接口说明和等同的 VHDL 之间的相似性。

需要指出的是上面所属的基本规则中有两个例外:存储器和总线接口类型都可以从 SystemC 代码的接口综合中推断出来。

人工接口说明也支持 C 和 C 设计,如果需要也能用;这意味着还是可以直接 定义接口,而不是让接口综合过程来推断。

整的 HLS 设计流还有更多的阶段,包括专门验证的部分。图 14.5 显示了完整的设计流,之后要逐一梳理。

图 14.5: Vivado HLS 设计流的概述

HLS 过程的输入

HLS 过程的主要输入是一个 C/C /SystemC 函数,以及一个基于 C 的测试集, 这个测试集是开发出来试验这个函数,然后验证运算是否正确的。这就需要用到一个 “ 黄金参考 ”,在综合中用来和函数所产生的输出做比对。黄金参考可能以预先准备好的输出值的形式存在,也可以是测试集本身的一部分。

功能性的验证

首先,有必要验证作为 HLS 输入的 C/C /SystemC 代码的功能完整性,然后才 开始做把它综合进 RTL 代码的过程。这可以用同一个高层语言写一个测试集,然后用某种形式的 “ 黄金参考 ” 比对所产生的结果来实现。比如,可以是一个预先准备好的已知是正确的输出测试向量的集合。

高层综合

下一步,是做 HLS 过程本身,这涉及到分析和处理基于 C 的代码,加上用户所给的指令和约束,来创建出回路的 RTL 描述。一旦 HLS 过程完成,就会产生一组输出文件,包括以所需的 RTL 语言写的设计文件。各种日志、输出文件,测试集、脚本等等也会被创建。

C/RTL 协同仿真

一旦做好了 HLS,产生了等价的 RTL 模型,就在 Vivado HLS 中通过 C/RTL 协同 仿真来与原本的 C/C /SystemC 代码做比对。这个过程要重用原本的基于 C 的测试集来给 HLS 所产生的 RTL 版本提供输入,然后拿它的输出与预期的值做比对。重要的是,这样就不再需要产生新的 RTL 测试集。SystemC 输出在这里特别有用,因为它实现了一种机制,在 HDL 仿真器不存在的情况下也能做验证。文献 [32] 给出了同时做 C 功能性验证和 C/RTL 协同仿真的好例子。

实现的评估

除了对设计的完整性做验证,还有必要评估 RTL 输出的实现和性能。比如,在 PL 中所需的资源的数量,设计的延迟、所支持的最高时钟频率等等。在 14.4.4 节会说明这些度量指标,然后在第 15 章进一步详细讨论。现在,只需要明白,作为设计者,我们可以通过施加给 HLS 过程的约束和指令来影响这个实现。

设计迭代

前面提到过,作为设计流的一部分,RTL 的实现会被评估,而如有必要,约束和指令会被精细调整,每个修订版本对应 Vivado HLS 专业术语中的一个新的 “ 解决方案 ”(14.4.6 进一步解释解决方案)。还可以对设计的评估做更多的基础性评审,然后对原本的算法做进一步的调整,也就是对用 C 代码进行的设计和 HLS 过程的输入做调整。

图 14.5 表达了从 C 的设计到创建出用于 RTL 综合的输出的步骤。注意在修改了指令和约束后,可以做多次 HLS 迭代,来找到 “ 最佳 ” 的解决方案;这对应了图的右侧的反馈回路。

如果设计者看到提示,然后修改输入的 C 代码,就会在设计过程中进入一个更大的回溯的步骤,这就是图中左侧的剪头所表明的。对 C 代码的任何修改都会导致功能性的重新验证,然后如果需要的话,后续的 HLS、C/RTL 验证和实现评估过程会重新做一遍。

RTL 输出

一旦设计被验证了,而且实现也迭代到了满足了期望的设计目标的地步了,就可以集成进更大的系统里了。这可以直接使用 HLS 过程所自动产生的 RTL 文件(即VHDL 或 Verilog 代码),不过也许用 Vivado HLS 的 IP 打包功能会更为方便。对 Vivado HLS 所产生的输出打包意味着 HLS 设计就可以被方便地引入其他 Xilinx 工 具,包括 Vivado IDE 里的 IP Integrator、XPS (用于 ISE 设计流)和 System Generator 里。

HLS 过程产生的 SystemC 输出能够用来做所产生的硬件的验证的,不过它们本身是不可以被综合的。

14.4.3 C 功能性验证和 C/RTL 协同仿真

既然验证如此重要,那么就很有必要来详细解释 C 的功能性验证和 C/RTL 协调仿真的过程。图 14.6 是这两件事情的图形化描述。

图的左侧所描述的,是一个基于 C 的测试集,已经被设计好用来创建和提供输入测试向量给功能性 C 模块。同样的测试向量会传递给一个 “ 已知良好 ” 的黄金参考设计,或是从一个预先准备好的文件读入黄金参考输出测试向量。参考设计的输出或是预先准备好的参考输出与 C 模块的输出做比对,如果两组结果一致,那么测试集就报告通过,否则就是失败。测试集还可以设计成报告总的错误的数量,或是针对结果给出其他自动化的反馈。

作为 Vivado HSL C/RTL 协同仿真过程的一部分,Vivao HLS 会自动产生一个等价的测试集配置(图 14.6 的右边部分)。这个测试集拿原本的 C 模块的 RTL 版本,也就是 HLS 的主输出,和黄金参考做比对,然后和上面一样产生成功与否的报告。

图 14.6: 在 Vivado HLS 中的 C 功能性验证和 C/RTL 协同仿真

C/RTL 协同仿真所需的所有文件都是由 Vivado HLS 自动产生的,这样就不再需要人工创建 RTL 测试集了。所产生的测试集包括必要的在基于 C 的测试集和被测的RTL 模块之间的数据传递的转换。

Vivado HLS 还能创建所产生的硬件的一个位真、周期精确的 System-C 模块, 这个模块可以在没有 RTL 仿真的情况下做协同仿真。

验证显然是设计过程中重要的一环,这些支持 RTL 级别测试的工具能提升生产效率。特别是,设计者不需要花费时间来给 RTL 仿真创建等价的测试集了,而且另外做测试集可能引入的错误也被消除了。不过,需要重点提醒的是,RTL 仿真是功能性的仿真,并不能反映实际的时序或总线协议行为。因此,它无法完全验证模块在非理想条件下的运作是否正确。

14.4.4 实现的度量指标和考虑因素

在这个阶段,有必要来定义作为设计过程组成部分的实现的度量指标和相关的考虑因素。这里以简易而且非正式的形式来做这件事情,这些问题会在第 15 章进一步展开。

  • 资源 / 面积 — 实现我的设计需要多少资源,以及所需的资源与目标 FPGA/ Zynq 芯片上可用的数量相比如何?
  • 吞吐率 — 能向这个设计馈送数据的速率是什么?是否满足我的应用的需要?
  • 时钟频率 — 在我的设计上能运行的最高时钟频率是多少?与系统的其他部分是否兼容?
  • 延迟 — 我的设计产生输出需要多少个时钟周期?一般情况下,这个延迟在这个系统中是否是可以接受的?
  • 功耗 — 我的设计在运行的时候要消耗多少能量?系统的这个部分是否对功耗敏感?
  • I/O 需求 — 我的设计的接口有多复杂?它们与系统的其他部件是否兼容?

以上的任何一个或全部因素,可能受到某种方式的约束,往往某些因素比其他更为优先。这通常都是由应用的需求所决定的。比如,一个用于低成本应用的系统,可能优先考虑资源最小化,以期利用较小的芯片;而另一方面,一个能快速适应输入变化的系统可能寻求的是延迟最小化和吞吐率最大化,而所仰赖的是资源的更大利用率。

有必要简要说明一下时钟不确定度这个术语。HLS 处理的目标是实现目标时钟周期减去时钟不确定度,这样就能给那些无法在 HLS 阶段确定的延迟留下空隙,比如 RTL 综合、布局和布线所带来的延迟。HLS 自然地认为模块是独立的,这样布线延迟只在系统集成阶段当系统被布出的时候才会完全暴露出来。时钟不确定度是用户定义的,默认的值是 12.5%[33]。

14.4.5 高层综合过程的概述

虽然我们已经讨论过了设计流的总体情况,还是应该更为详细地考虑一下 HLS 的过程。因此这一节会总结在对 C、C 、SystemC 设计文件做 HLS 来得到等价的 RTL的过程中所涉及到的步骤。作为实际的例子,我们用 C 来做设计语言。

还记得在 14.4.1 节中,HLS 过程做了 ( 一 ) 算法综合和 (二)接口综合 (如果接口不能直接指定的话)。这里我们关注的是前者。

除了设计文件本身以外,这个过程还有一些其他的输入,包括某个特定目标芯片的规格和设计者提供的指令与约束。正如将在 14.4.6 节所讨论的,这些会直接影响 HLS 所产生的实现。为了方便目前的讨论,我们假设目标芯片是确定的,而且所施加的约束和指令也是不变的。

算法综合包括三个主要阶段,依次是:

1. 解析出数据通路和控制;

2. 调度和绑定;

3. 优化下面将依次简单解释每一阶段。

解析出数据通路和控制

HLS 的第一个阶段是分析 C/C /SystemC 代码,并且解释所需的功能。比如, 这可以包括:逻辑和算法的运算、条件语言和分支、数组运算和循环。

所产生的实现会具有一个数据通路元件,一般还会有一个控制元件。需要澄清的是,这里的 “ 数据通路 ” 处理指的是在数据样本上作的运算,而 “ 控制 ” 是需要协同数据流处理所需的电路。算法的本质基本地定义出数据通路和控制元件,但是,在第 15 章会看到,设计者可以在 HLS 中采取专门的步骤来最小化控制元件的复杂度。

调度和绑定

HLS 是由两个主要过程组成的:调度和绑定。它们是交替进行的,如图 14.7 所示,彼此互相影响。下面总结了这两个过程中所做的操作。

  • 调度是把由 C 代码解释得到的 RTL 语句翻译成一组运算,每个都关联着一定的时钟周期的执行时间。这个阶段所作的决策,是受时钟频率和不确定度、目标芯片的技术和用户所施加的指令所影响的。
  • 绑定是调度好了的运算和目标芯片上的实际资源联系起来的过程。这些资源的功能和时序特征可能会影响调度,因此绑定的数据会反馈给调度过程。比如用了 DSP48x 资源就表明要用到一条比采用逻辑片的方案要短一些的严格的通路。

图 14.7: Vivado HLS 的调度和绑定过程

比如,如果综合出来的算法需要做一组算术运算,HLS 过程就必须根据目标的 时钟频率和不确定度来决定如何调度这些运算 (要分配多少个时钟周期来做完),以及如何绑定这些运算(也就是如何把运算映射到 PL 上的可计算资源里)。还记得C 的源代码并不能表达或指定硬件架构,但是施加指令的话,源代码确实可以产生不同的架构。

结果的实现具有一些特征,主要是 (一)延迟、(二)吞吐率和 (三)所用到 的资源量。

为了说明问题,假设一个 C 的算法要计算输入有十个数字的数组的平均值。这表明要做的计算是:

• 用 9 个加法来得到总和;然后

• 乘以 0.1 来计算平均数。

在调度和绑定这些运算的时候有一些不同的选项。一种可能是用一个加法器和 一个乘法器,在几个时钟周期里串行计算。另一种方法是,关键通路也许能允许以目标频率在一个时钟周期内做多个计算,这样就能实现低延迟和高吞吐率。

图 14.8 描绘了三种可能,特别考虑的是实现的特征之间的不同。

1. 第一种实现用了最少的资源 (一个加法器和一个乘法器,都是由逻辑部分构成的),并且有 11 个时钟周期的延迟。这个设计的吞吐率低 —— 1/11 个时 钟周期 —— 因为新的计算要到前一个计算完成才能开始 (假设这里没有使 用流水线,这是后面第 15 章要解释的)。

2. 根据目标的技术,HLS 过程判定在满足时序约束下,每个时钟周期可以做三个加法运算。这个结果用了芯片上较多的资源,但是具有较短的延迟和较高的吞吐率。

3. 最后,它发现,如果用 DSP48x 片来代替逻辑资源,所有的运算可以在一个时钟周期内完成。这成为最贵的实现,总共需要 9 个 DSP48x 片 (前 8 个加法每个要一个,最后一个加法和乘法组合在一个 DSP48x 片里),但是具有低得多的延迟 (1 个时钟周期)和相当于时钟速率的吞吐率。这种形式的实现当

然只有在能满足时序约束的情况下才能实现 —— 否则的话 Vivado HLS 可能会插入流水线寄存器来满足时序要求。

图 14.8: 一个函数算例中从 HLS 中得到的三种可能性结果的比较

HLS 过程会默认优化面积,也就是会采用上面所列的第一种策略,消耗最少的资源。这种实现的缺点是具有较长的延迟和较低的吞吐率,这可能无法满足应用的需求。不过,设计者可以通过给 HLS 过程定义约束和指令来施加对调度和绑定的影响,从而以另外的方式做优化。

优化

前面提到过,设计者有手段可以让高层综合朝向他 / 她的实现目标努力。有两种方法可以用来调整 HLS 过程的行为,从而影响结果:

  • 约束 — 设计者可以对设计的某些指标加以限制。比如,可以指定最低的时钟周期。这样就能方便地确保做出来的实现能满足要集成进去的系统的要求。类似的,设计者可以选择约束资源的利用情况或其他的条件,从而优化应用的设计。
  • 指令 — 设计者可以通过指令对 RTL 的实现参数施加更具体的影响。有各种类型的指令,分别映射在代码的某些特征上,比如让设计者可以指定 HLS 引擎如何处理 C 代码中识别出来的循环或数组,或是某个特定运算的延迟。这能导致RTL 输出的巨大改变。因此,具有了指令的知识,设计者就可以根据应用的需求来做优化了。

关于 RTL 的输出

用户有选项可以指定所产生的输出文件所用的 RTL 语言,并且可以从 VHDL、 Verilog 和 SystemC 中选择。当然,需要指出的是,SystemC 也是 HLS 可用的输入语言之一,因此第一眼看到它也被列在输出类型中也许会有所好奇。不过,作为 HLS的输出所产生的 SystemC 文件是对硬件的 RTL 描述,也就是比 HLS 的输入要更低级的表达。

对于其他 HLS 输出语言 (VHDL 和 Verilog)也是一样,实现是基于所选的目标芯片的。当没有 RTL 仿真器的时候,这样的输出对于验证设计会特别有用。

14.4.6 解决方案:探索设计空间

一个 Vivado HLS 项目是由一组设计文件、一组测试集文件和项目设置所组成的。项目可以具有多个解决方案 —— 这个术语很重要,因为它和 “ 探索设计空间 ” 有关,也就是产生一系列可能的实现,这些实现可以被比较,然后从中选出最适合的版本。

要理解的是,每个解决方案是同一个 C/C /SystemC 源代码的不同的实现。所综合的 RTL 方案的不同,是由四个因素所决定的:

• 目标的技术和型号 (如 Virtex-7、Kintex-7、Zynq-7000...)

• 目标的时钟频率

• 所施加的实现约束

• 用户定义的综合指令

对于一个确定的应用,前两个 (目标技术和型号)往往是不变的,但正如上一 节所讨论的,设计者能改变实现约束和综合指令来对所产生的解决方案施加影响。

在第 15 章,和接口与算法综合相关的部分还会进一步仔细定义。一旦创建,每个解决方案里包含了关于目标、所施加的指令和约束以及所获得的结果的数据。

下一章还会详细讨论的是,由于资源成本、吞吐率和延迟的不同,从一组解决方案获得的结果也会有所不同。这些都可以根据任务的需要而做出探索,进而精细调整。

14.4.7 Vivado HLS 库的支持

需要指出的是,Vivado HLS 带有对算术和数学函数的支持,以及线性代数、视 频处理、DSP 等。文献 [33] 中有完整的库的细节支持数据。

14.5 在 Zynq 设计流中的 HLS

在 14.4.2 节中把 Vivado HLS 的设计流概述为一个独立的过程。不过,我们还 必须在 Zynq 的设计流中来考虑这个问题。

HLS 是创建能被包含进一个基于 Zynq 的系统的功能性模块或 IP 包的设计方法。用 HLS 设计出来的 IP 包是用于在目标 Zynq 芯片的 PL 部分做实现的。在一个具体的Zynq 系统设计中可能有多个这样的模块存在,而设计任务的一部分工作就是要恰当地建立它们与设计的其他部分之间的接口(比如用 AXI 连接)。回顾 53 页的图 3.2,这对应的是标着“Vivado HLS / HDL / System Generator”的阶段 —— 用Vivado HLS 创建出能作为 IP 包集成进设计的模块。

当 Vivado HLS 可以用来描述常用的功能性模块,诸如最基本的 FIR 过滤器和 FFT,设计者应该要注意到对于这些运算的专门的、优化的支持已经存在了,并且通过 IP Integrator 的 IP Catalog 或 System Generator 工具的 Xilinx BlockSet 就 可以获得。同样的功能可以通过调用所提供的库中的函数 (如 FFT 或 FIR 函数)来引入到 Vivado HLS 设计中。这些函数的详细数据可以从 《Vivado Design Suite User Guide: High-Level Synthesis》[33] 中获得。HLS 也是用于开发那些在已有 的 IP 目录中无法找到与其等价的定制功能的非常强大的方法。

14.6 本章回顾

本章介绍了高层综合的概念,并且解释了它作为一种设计方法,日益增长的重要性,特别是在 Zynq 和 SoC 设计中。HLS 允许用软件语言在较高的抽象层次上定义算法,然后在高层综合工具的辅助下将这个算法转换成 RTL 描述。这个设计方法能极大地提高在设计能力和验证效果方面的生产率。

本章介绍了 Vivado HLS 工具,也描述了它的设计流。特别指出的是,除了综合本身,Vivado HLS 流还集成了在功能级别做流化验证的手段,而且还能进一步对所产生的 RTL 代码做验证。

在本章快结束的时候,我们介绍了采用 HLS 的过程,以及设计者能用来对这些过程及其结果施加影响的机制。我们描述了标准的实现度量指标和考虑因素,并且指出从同一组 Vivado HLS 输入文件中可以产生多个 “ 解决方案 ”。这样就能针对设计者优先考虑的关键因素,对实现的可能性、以关键指标做的评估和优化,做出探索。

下一章,我们会仔细看看如何用 Vivado HLS 来创建设计,从而建立起这样的一个概念框架来。

14.7 参考文献

说明:所有的 URL 最后在 2014 年 6 月访问过。

[1] Accellera Systems Initiative 网站 ,位于 : http://www.accellera.org/

[2] P. Banerjee, “Overview of a compiler for synthesisizing MATLAB programs onto FPGAs”, IEEE Transactions on VLSI Systems, Vol. 12, Issue 3, March 2004, pp. 312-324.

[3] Berkeley Design Technology, Inc., “An Independent Evaluation of: High-Level Synthesis Tools for Xilinx FPGAs”, consultation paper, 2010. 位于 : http://www.xilinx.com/technology/dsp/BDTI_techpaper.pdf

[4] J. Bier and J. E. White, “BDTI Study Certifies High-Level Synthesis Flows for DSP-Centric FPGA Design”, Xilinx Xcell Journal, Issue 71, second quarter 2010, pp. 12 - 17. 位于 : http://www.xilinx.com/publications/archives/xcell/Xcell71.pdf

[5] D. C. Black, J. Donovan, B. Bunton and A. Keist, SystemC: From the Ground Up, 2nd Edition, Springer, 2009.

[6] M. Burton, J. Aldis, R. Günzel and W. Klingauf, “Transaction Level Modelling: A reflection on what TLM is and how TLMs may be classified”, Forum on Design Languages, 2007, pp. 92-97.

[7] Cadence, C-to-Silicon Compiler 网页 ,位于 : http://www.cadence.com/products/sd/silicon_compiler/pages/default.aspx

[8] J. M. P. Cardoso and H. C. Neto, “Towards an Automatic Path from Java Bytecodes to Hardware Through High-Level Synthesis”, Proceedings of the IEEE International Conference on Electronics, Circuits and Systems, 1998, vol. 1, pp. 85-88.

[9] D. Gajski and R. Kuhn, “Guest Editors’ Introduction: New VLSI Tools”, Computer, vol. 16, no.12, pp.11 - 14, December 1983.

[10]D. Gadski, T. Austin and S. Svoboda, “What Input-Language is the Best Choice for High Level Synthesis (HLS)?”, panel session, Proceedings of the 47th ACM/IEEE Design Automation Conference (DAC), pp. 857-858, June 2010.

[11]D. Große and R. Drechsler, Quality-Driven SystemC Design, Springer, 2010.

[12]R. Gupta and F. Brewer, “High-Level Synthesis: A Retrospective” in High-Level Synthesis: From Algorithm to Digital Circuit, edited by P. Coussy and A. Morawiec, Springer, 2008.

[13]M. Haldar, A. Nayak, A. Choudhary and P. Banerjee, “FPGA Hardware Synthesis from MATLAB”, Proceedings of the 14th International Conference on VLSI Design, January 2001, pp. 299-304.

[14]IEEE Computer Society, “IEEE Standard for Standard SystemC Language Reference Manual”, IEEE Std 1666-2011, January 2012.

[15]Impulse Accelerated Technologies, Impulse CoDeveloper C-to-FPGA Tools product 网页 .位于 : http://www.impulseaccelerated.com/products_universal.htm

[16]International Organization for Standardization, “ISO/IEC 9899:2011: Information technology - Programming languages - C”, 2011. [17]International Organization for Standardization, “ISO/IEC 14882:2011: Information technology - Programming languages - C ”, 2011.

[18]B. W. Kernighan and D. M. Ritchie, The C Programming Language, Prentice Hall, 1978.

[19]T. Kuhn and W. Rosenstiel, “Java Based Object Oriented Hardware Specification and Synthesis”, Proceedings of the Asia and South Pacific Design Automation Conference, 2000, pp. 579-581.

[20]M. C. McFarland, A. C. Parker, and R. Camposano, “The High-Level Synthesis of Digital Systems”, Proceedings of the IEEE, vol. 78, no.2, pp 301 - 318, Feb 1990.

[21]G. Martin and G. Smith, “High Level Synthesis: Past, Present and Future”, IEEE Design and Test of Computers, Vol. 26, Issue 4, July/August 2009, pp. 18 - 24.

[22]A. Mathur, E. Clarke, M Fujita, and R. Urard, “Functional Equivalence Verification Tools in High-Level Synthesis Flows”, IEEE Design & Test of Computers, July/August 2009, pp. 88 - 95.

[23]Mathworks, HDL Coder product 网页 . 位于 : http://www.mathworks.com/products/hdl-coder/

[24]Mentor Graphics, Handel-C Synthesis Methodology 网页 . 位于 : http://www.mentor.com/products/fpga/handel-c/

[25]M. Meredith and S. Svoboda, “The Next IC Design Methodology Transition is Long Overdue”, Open SystemC Initiative, February 2010. 位于 : http://www.accellera.org/resources/articles/icdesigntrans/community/articles/icdesigntrans/ ic_design_transition_feb2010.pdf

[26]D. M. Ritchie, “The Development of the C Language”, Proceedings of the 2nd History of Programming Languages Conference, Cambridge, Massachusetts, April 1993.

[27]M. Santarini, “Xilinx Unveils Vivado Design Suite for the Next Decade of ‘All Programmable’ Devices”, Xilinx Xcell Journal, Issue 79, second quarter 2012, pp. 8 - 13. 位于 : http://www.xilinx.com/publications/archives/xcell/Xcell79.pdf

[28]R. Thomson, V. Chouliaras and D. Mulvaney, “The Hardware Synthesis of a Java Subset”, Proceedings of the Norchip Conference, 2006, pp. 217-220.

[29]H. Trickey, “Flamel: A High-Level Hardware Compiler”, IEEE Transactions on Computer-Aided Design, Vol. CAD-6, No. 2, March 1987, pp. 259 - 269.

[30]Xilinx, Inc., Press Release: “Xilinx Acquires AutoESL to Enable Designer Productivity and Innovation with FPGAs and Extensible Processing Platform”, 30th January, 2011. 位于 : http://press.xilinx.com/2011-01-30-Xilinx-Acquires-AutoESL-to-Enable-Designer-Productivityand-Innovation-With-FPGAs-and-Extensible-Processing-Platform

[31]Xilinx, Inc., “UG634 - AccelDSP Synthesis Tool User Guide”, v11.4, December 2009.位于 : http://www.xilinx.com/support/documentation/sw_manuals/xilinx11/acceldsp_user.pdf

[32]Xilinx, Inc., “UG871 - Vivado Design Suite Tutorial: High Level Synthesis”, v2014.1, May 2014.位于 : http://www.xilinx.com/support/documentation/sw_manuals/xilinx2014_1/ug871-vivado-highlevel-synthesis-tutorial.pdf

[33]Xilinx, Inc, “UG902 - Vivado Design Suite User Guide: High-Level Synthesis”, v2014.1, May 2014.位于 : http://www.xilinx.com/support/documentation/sw_manuals_j/xilinx2014_1/ug902-vivado-highlevel-synthesis.pdf

[34]J. Yi and H. Kwon, “Samsung’s Viewpoints for High-Level Synthesis” in High-Level Synthesis: From Algorithm to Digital Circuit, edited by P. Coussy and A. Morawiec, Springer, 2008.

第二十六篇到此结束,下一篇将带来第二十七篇,开启第十五章,Vivado HLS: 近视等相关内容。欢迎各位大侠一起交流学习,共同进步。

END

后续会持续更新,带来Vivado、 ISE、Quartus II 、candence等安装相关设计教程,学习资源、项目资源、好文推荐等,希望大侠持续关注。

大侠们,江湖偌大,继续闯荡,愿一切安好,有缘再见!

0 人点赞