综合顶级函数时,该函数的参数arguments(或参数parameters)将综合到RTL端口中。 此过程称为接口综合。
#include "sum_io.h"
dout_t sum_io(din_t in1, din_t in2, dio_t *sum) {
dout_t temp;
*sum = in1 + in2 + *sum;
temp = in1 + in2;
return temp;
}
上面的示例包括:
默认情况下,将向设计中添加块级接口协议。这些信号控制块,独立于任何端口级I/O协议。这些端口控制块何时可以开始处理数据(ap_start),何时可以接受新输入(ap_ready),以及设计是否空闲(ap_idle)或完成了操作(ap_done)。
最终一组信号是数据端口。创建的I/O协议取决于C参数的类型和默认值。在使用块级协议启动块的操作之后,使用端口级IO协议将数据按顺序输入和输出块。
默认情况下,按值传递参数和指针的输入被实现为简单的连接端口,没有相关的握手信号。在上面的例子中,输入端口是在没有I/O协议的情况下实现的,只有一个数据端口。如果端口没有I/O协议,(默认或设计)输入数据必须保持稳定,直到读取它。
默认情况下,输出指针是带有一个输出有效信号vld来实现的,以指示输出数据何时有效。如果没有与输出端口相关联的I/O协议,则很难知道何时读取数据。
同时读取和写入的函数自变量被拆分为单独的输入和输出端口。
如果函数有返回值,则使用输出端口ap_return来提供返回值。当设计完成一个事务时(这相当于C函数的一次执行)块级协议指示该函数已使用ap_done信号完成。这还表明端口ap_return上的数据是有效的,可以读取。
注意:顶级函数的返回值不能是指针。 Note: The return value to the top-level function cannot be a pointer
通过接口综合创建的接口类型取决于C参数的类型,默认接口模式和INTERFACE优化指令。
Interface Synthesis Reference包含接口协议的完整细节,包括波形图。以下提供了每种接口模式的概述。
块级接口协议是ap_ctrl_none、ap_ctrl_hs和ap_ctrl_chain。这些是指定的,并且只能在函数或函数返回上指定。当指令在GUI中指定时,它将把这些协议应用于函数返回。即使函数不使用返回值,也可以在函数返回时指定块级协议。
前面示例中描述的ap_ctrl_hs模式是默认协议。ap_ctrl_chain协议类似于ap_ctrl_hs,但是有一个额外的输入端口ap_continue,它提供来自使用这个块中的数据的块的反压。如果函数完成时ap_continue端口为逻辑0,则块将停止操作,下一个事务将不继续进行。只有当ap_continue被断言为逻辑1时,下一个事务才会继续。
ap_ctrl_none模式实现了没有任何块级I/O协议的设计。
如果函数返回也指定为AXI4-Lite接口(s_axilite),则块级接口中的所有端口都分组到AXI4-Lite接口中。当使用另一个设备(如CPU)来配置和控制这个块何时启动和停止操作时,这是一种常见的实践。
Vivado HLS支持的AXI4接口包括AXI4- stream (axis)、AXI4- lite (s_axilite)和AXI4 master (m_axi)接口,可以这样指定:
AXI4- stream接口:仅指定输入参数或输出参数,而不指定输入/输出参数。
AXI4-Lite接口:指定除流之外的任何类型的参数。您可以将多个参数分组到同一个AXI4-Lite接口中。
AXI4 master接口:仅指定数组和指针(以及c++中的引用)。您可以将多个参数分组到同一个AXI4接口中。
ap_none和ap_stable模式不向端口添加I/O协议
ap_hs、ap_vld、ap_ovld
模式ap_hs包括一个带有数据端口的双向握手信号。
模式ap_vld只有一个有效端口,ap_ack只有一个确认端口。
模式ap_ovld与in-out参数一起使用。当in-out被分割为单独的输入和输出端口时,模式ap_none应用于输入端口,ap_vld应用于输出端口。这是读&写指针参数的默认值。
ap_hs模式可以应用于按顺序读写的数组。如果Vivado HLS可以确定读或写访问不是顺序的,它将停止合成与一个错误。如果无法确定访问顺序,Vivado HLS将发出警告。
默认情况下,数组参数作为ap_memory接口实现。这是一个标准的块RAM接口,具有数据、地址、芯片启用和写启用端口。
ap_memory可以实现为双端口或单端口 。如果Vivado HLS能够确定使用双端口接口将缩短初始间隔II,则会自动实现双端口接口。RESOURCE指令用于指定存储资源,如果该指令数组呗指定a single-port block RAM,则将实现单端口接口。相反,如果使用RESOURCE指令指定了一个双端口接口,如果Vivado HLS确定这个接口没有任何好处,那么它将自动实现一个单端口接口。
bram接口模式的功能与ap_memory接口相同。唯一的不同是在Vivado IP Integrator中如何实现端口:
如果以顺序方式访问数组,则可以使用ap_fifo接口。与ap_hs接口一样,如果Vivado HLS确定数据访问不是顺序的,它将停止访问;如果Vivado HLS无法确定访问是否是顺序的,则报告警告;如果Vivado HLS确定访问是顺序的,则不发出消息。ap_fifo接口只能用于读或写,不能同时用于读和写。
ap_bus接口可以与总线桥进行通信。该接口不遵循任何特定的总线标准,但足够通用,可以与总线桥接一起使用,而总线桥接又与系统总线进行仲裁。总线桥必须能够缓存所有的突发写。
默认情况下,接口上的结构分解为它们的成员元素,并且为每个成员元素分别实现端口。在没有INTERFACE指令时,将实现该结构的每个成员元素。结构体的数组被实现为多个数组,每个结构成员都有一个单独的数组。 DATA_PACK优化指令用于将结构的所有元素打包到单个宽向量中。这允许同时读取和写入结构的所有成员。将结构的成员元素按照它们在C代码中出现的顺序放入向量中:结构的第一个元素与向量的LSB对齐,结构的最后一个元素与向量的MSB对齐。结构中的所有数组都被划分为单独的数组元素,并按从低到高的顺序放置在向量中。
Note:DATA_PACK优化不支持包含其他结构的打包结构。
使用多次访问的指针可能会在综合之后引入意外的行为。在下面的示例中,指针d_i被读取四次,指针d_o被写入两次:指针执行多次访问。
Interface synthesis由接口指令或使用配置设置来控制。要指定端口上的接口模式,请在GUI选项卡中选择端口,然后右键单击鼠标打开Vivado HLS指令编辑器,如下图所示
Vivado HLS指令编辑器,设置以下选项:
• mode
Select the interface mode from the drop-down menu.
• register
选择此选项,则在操作的第一个周期中执行所有按值传递pass-by-value的读取。对于输出端口,register选项确保输出registered。您可以将register选项应用于设计中的任何函数。对于memory、FIFO和AXI4接口,register选项不起作用。
• depth
This option specifies how many samples are provided to the design by the test bench and how many output values the test bench must store. Use whichever number is greater.
Note: 在单个事务中多次读取或写入指针的情况,C / RTL co-simulation需要使用depth选项 。对于数组或使用hls::stream构造时,深度选项不是必需的。只有在接口上使用指针时才需要它。
如果深度选项设置得太小,C/RTLco-simulation可能会死锁deadlock,如下所示:
• port
This option is required. By default, Vivado HLS does not register ports.
Note: To specify a block-level I/O protocol, select the top-level function in the Vivado HLS GUI, and specify the port as the function return.
• offset
This option is used for AXI4 interfaces.
要设置接口配置,请选择Solution → Solution Settings → General →config_interface。 您可以使用配置设置来:
任何C函数都可以使用全局变量:在任何函数范围之外定义的那些变量。 默认情况下,全局变量不会导致创建RTL端口:Vivado HLS假定全局变量位于最终设计中。 config_interface配置设置Exposure_global指示Vivado HLS为全局变量创建端口。
ug902-High-Level Synthesis Reference Guide
Syntax
set_directive_interface [OPTIONS ] <-location> <-port>
• <-location> is the location (in the format function[/label]) where the function interface or registered output is to be specified.
• <-port> is the parameter (function argument or global variable) for which the interface has to be synthesized. This is not required when modes ap_ctrl_none or ap_ctrl_hs are used.
Options
-bundle :将函数参数分组到AXI端口。默认情况下,Vivado HLS将作为AXI4-Lite接口指定的所有函数参数分组到单个AXI4-Lite端口。类似地,Vivado HLS将作为AXI4接口指定的所有函数参数分组到一个AXI4端口。
bundle选项显式地将所有具有相同的函数参数分组到相同的接口端口,并将RTL端口命名为。
-mode (ap_none|ap_stable|ap_vld|ap_ack|ap_hs|ap_ovld|ap_fifo| ap_bus|
ap_memory|bram|axis|s_axilite|m_axi|ap_ctrl_none|ap_ctrl_hs |ap_ctrl_chain)
ap_none:没有协议。接口是一个数据端口。
ap_stable:没有协议。接口是一个数据端口。Vivado HLS假设数据端口在重置后总是稳定的,这允许内部优化掉不必要的寄存器。
ap_vld:使用valid指示数据何时可以有效读写。
ap_ack:使用关联的acknowledge端口实现数据端口,以确认数据已被读取或写入。
ap_hs:实现具有关联的valid and acknowledge端口的数据端口,以提供双向握手来指示何时数据对读写有效,并确认数据已被读写。
ap_ovld:使用关联的valid端口实现输出数据端口,以指示数据何时可以有效读写。
注意:Vivado HLS implements the input argument or the input half of any read/write arguments with mode ap_none.
ap_fifo:使用标准的FIFO接口实现端口,使用数据输入和输出端口,并使用相关的active-Low FIFO空端口和满端口。
注意:只能对读参数或写参数使用此接口。ap_fifo模式不支持双向读/写参数。
ap_bus:将指针和引用传递端口作为总线接口实现。
ap_memory:将数组参数作为标准的RAM接口实现。如果在Vivado IP integrator中使用RTL设计,则内存接口显示为离散端口。将数组参数作为标准RAM接口实现。如果在Vivado IP integrator中使用RTL设计,则内存接口显示为单个端口。
axis:将所有端口作为AXI4-Stream接口实现。
s_axilite:将所有端口实现为AXI4-Lite接口。Vivado HLS在导出RTL过程中生成一组相关的C驱动程序文件。
m_axi:将所有端口都实现为AXI4接口。您可以使用config_interface命令来指定32位(默认)或64位地址端口,并控制任何地址偏移量。
ap_ctrl_none:没有块级I/O协议。注意:使用ap_ctrl_none模式可能会阻止使用C/RTL联合仿真特性验证设计。
ap_ctrl_hs:实现一组块级控制端口来启动设计操作,并指示设计何时空闲、何时完成,以及何时为新的输入数据做好准备。
Note: The ap_ctrl_hs是block-level I/O 默认协议.
ap_ctrl_chain:实现一组块级控制端口,用于启动设计操作、继续操作,并指示设计何时空闲、何时完成,以及何时准备好新的输入数据。
接口综合只对顶层函数及其参数有用。
默认情况下,block-level interface protocol 会被自动添加到设计中,这些接口控
制着整个块(即顶层函数),独立于任何 port-level I/O protocol。
block-level interface protocol 只作用于顶层函数或者顶层函数的返回值(不作用于顶层函数的参数),该协议只有三种,
ap_ctrl_none
ap_ctrl_hs
ap_ctrl_chain
Vivado HLS使用接口类型ap_ctrl_none、ap_ctrl_hs和ap_ctrl_chain来指定RTL是否使用块级握手信号实现。块级握手信号指定以下内容:
可以在函数或函数返回上指定这些块级I/O协议。如果C代码没有返回值,您仍然可以在函数返回时指定块级别的I/O协议。如果C代码使用函数返回,Vivado HLS将为返回值创建输出端口ap_return。
ap_ctrl_hs块级I/O协议是默认的。下图显示了Vivado HLS在一个函数上实现ap_ctrl_hs时的结果RTL端口和行为。在本例中,函数使用return语句返回一个值,Vivado HLS在RTL设计中创建ap_return输出端口。如果函数return statement未包含在C代码中,则不创建此端口。
ap_ctrl_chain接口模式类似于ap_ctrl_hs,但提供了ap_continue来施加反压(back pressure)。Xilinx建议在将Vivado HLS块链接在一起时使用ap_ctrl_chain块级I/O协议。
ap_ctrl_none块级I/O协议,则不会创建块级I/O协议中显示的握手信号端口(ap_start、ap_idle、ap_ready和ap_done)。
如果在设计上没有指定块级I/O协议,那么在使用C/RTL cosimulation验证RTL设计时,必须遵守接口综合要求(Interface Synthesis Requirements)中描述的条件。
ap_start (in) 为高表示代码块可以开始处理数据,这时
ap_idle (out)就为低,表明模块处于非空闲状态。
ap_ready (out) 如果为高,表明这个模块可以接收新的数据,
ap_done( out)为高则表明已经处理完结果了。
下图显示了ap_ctrl_hs I/O协议为非流水线non-pipelined 设计创建的块级握手信号的行为。
复位后,
ap_ctrl_chain块级I/O协议类似于ap_ctrl_hs,但提供了ap_continue额外输入端口。ap_continue信号为High表示使用输出数据的下游块downstream block已经准备好接受新的数据输入。如果下游块不能使用新的数据输入,则ap_continue为低,将阻止上游块 upstream blocks 生成其他数据。
下游块的ap_ready端口可以直接驱动ap_continue端口。以下是关于ap_continue端口的附加信息:
下图中,第一个事务完成,第二个事务立即启动,因为ap_done高时ap_continue高。但是,设计在第二个事务结束时停止,直到ap_continue为高值。
ap_none端口级I/O协议是最简单的接口类型,没有与之关联的其他信号。输入和输出数据信号都没有关联的控制端口来指示何时读取或写入数据。RTL设计中惟一的端口是源代码中指定的端口。
ap_none接口不需要额外的硬件开销。然而,ap_none接口需要以下:
1,Producer blocks执行以下操作之一:
2,Consumer blocks 在正确的时间读取输出端口。
注意:ap_none接口不能用于数组参数。
与ap_none一样,ap_stable协议不向设计中添加任何接口控制端口。
ap_stable类型通常用于可以更改但在正常操作期间保持稳定的数据,比如提供配置数据的端口。ap_stable类型通知Vivado HLS以下内容:
ap_hs端口级I/O协议在开发过程中提供了最大的灵活性,允许自底向上和自顶向下的设计流。双向握手可以安全地进行所有块内通信,不需要人工干预或假设就可以进行正确的操作。ap_hs端口级I/O协议提供以下信号:
• 数据端口
• 确认信号,指示何时使用数据
• 读取数据时的有效信号
下图显示了ap_hs接口对输入和输出端口的行为。在本例中,输入端口命名为In,输出端口命名为out。
注意:控制信号名称基于原始端口名称。例如,数据输入的有效端口名为in_vld。
ap_ack端口级I/O协议是ap_hs接口类型的子集。
CAUTION!不能使用C/RTL cosimulation来验证在输出端口上使用ap_ack的设计。
信号:数据端口、确认信号(指示何时使用数据)
ap_vld是ap_hs接口类型的一个子集。
信号:数据端口、数据vld
○ For input arguments, the design reads the data port as soon as the valid is active. Even if
the design is not ready to read new data, the design samples the data port and holds the
data internally until needed.
○ For output arguments, Vivado HLS implements an output valid port to indicate when the
data on the output port is valid.
ap_ovld是ap_hs接口类型的一个子集。
信号:数据端口、数据vld
valid
〇对于输入参数和inout参数的输入部分,设计默认为类型ap_none。
〇输出参数和输出inout参数的一半,设计实现类型ap_vld
ap_memory和bram端口级I/O协议用于实现数组参数。当实现需要随机访问内存地址位置时,这种端口级I/O协议可以与存储元素(例如ram和rom)通信。
注意:如果顺序访问存储元素,那么可以使用ap_fifo接口。ap_fifo接口减少了硬件开销,因为不需要地址生成。
ap_memory和bram接口端口级I/O协议是相同的。唯一的区别是Vivado IP integrator显示模块的方式:
提示:在运行合成之前,确保使用RESOURCE指令将数组参数定向到正确的内存类型。不同的memory会产生不同的schedule and RTL.
下图显示了一个名为d的数组,它被指定为一个单端口块RAM。端口名基于C函数参数。例如,如果C参数是d, chip_enable是d_ce,输入数据是基于BRAM的输出/q端口的d_q0。
Note::对于默认块RAM,设计期望输入数据d_q0在下一个时钟周期中可用。可以使用RESOURCE指令来指示RAM具有更长的读取延迟。
当一个输出端口被写出时,它的输出有效信号接口是最硬件有效的方法,当需要访问一个存储元素,并且访问总是以顺序的方式执行,不需要随机访问。ap_fifo端口级I/O协议支持以下内容:
•允许端口连接到FIFO
•支持完整的、双向的empty-full的通信
•适用于数组、指针和引用传递参数类型
注意:可以使用ap_fifo接口的函数通常使用指针,并且可能多次访问同一变量。
要了解在使用这种编码风格时volatile限定符的重要性,请参阅Multi-Access Pointer Interfaces: Streaming Data.
在下面的例子中,in1是一个指针,先访问当前地址,然后访问当前地址上面的两个地址,最后访问下面的一个地址。
void foo(int* in1, ...) {
int data1, data2, data3;
...
data1= *in1;
data2= *(in1+2);
data3= *(in1-1);
...
}
如果in1被指定为ap_fifo接口,Vivado HLS将检查访问,确定访问顺序不一致,并发出一个错误,然后停止。要从非连续地址位置读取数据,请使用ap_memory或bram接口。
不能在读取和写入的参数上指定ap_fifo接口。只能在输入或输出参数上指定ap_fifo接口。将输入参数in和输出参数out指定为ap_fifo接口的设计如下图所示。
axis模式指定一个axi4流I/O协议。有关AXI4流接口的完整描述(包括定时和端口),请参阅Vivado设计套件:AXI Reference Guide
(UG1037)。有关使用此I/O协议的全部功能的信息,请参阅Using AXI4 Interfaces。
s_axilite模式指定一个AXI4-Lite从I/O协议。有关AXI4-Lite从接口的完整描述(包括时间和端口),请参阅Vivado设计套件:AXI参考指南(UG1037)。有关使用此I/O协议的全部功能的信息,请参阅Using AXI4 Interfaces。
m_axi模式指定了一个AXI4主I/O协议。有关AXI4主接口(包括timing和端口)的完整描述,请参阅Vivado设计套件:AXI参考指南(UG1037)。有关使用此I/O协议的全部功能的信息,请参阅Using AXI4 Interfaces。
ch1-Verifying the RTL-Automatically Verifying the RTL
要使用C/RTL协同仿真特性来验证RTL设计,至少满足以下条件之一:
如果这些条件中至少有一个不满足,C/RTL联合模拟将使用以下消息停止
@E [SIM-345] Cosim only supports the following 'ap_ctrl_none' designs:
(1)combinational designs;
(2) pipelined design with task interval of 1;
(3)designs with array streaming or hls_stream ports.
@E [SIM-4] *** C/RTL co-simulation finished: FAIL ***
IMPORTANT! 如果设计指定使用块级别的IO协议ap_ctrl_none,并且设计包含任何使用非阻塞行为的hls::stream变量,则不能保证C/RTL协同仿真能够完成。
如果将任何顶级函数参数指定为axil - lite接口,则函数返回也必须指定为axil - lite接口。
反压的接口可以使用ap_ctrl_chain
CAUTION!不能使用C/RTL cosimulation来验证在输出端口上使用ap_ack的设计。
ap_memory接口以离散端口的形式出现
ap_fifo适用于数组、指针和引用传递参数类型
ap_hs模式可以应用于按顺序读写的数组。如果Vivado HLS可以确定读或写访问不是顺序的,它将停止合成与一个错误。如果无法确定访问顺序,Vivado HLS将发出警告。
注意:顶级函数的返回值不能是指针。 Note: The return value to the top-level function cannot be a pointer