这是针对pragma HLS interface 语法的翻译笔记,可以作为原英文文档的辅助文档,原文地址是SDSoc Development Help
在vivado HLS基于C的设计中,函数形式参数代表了输入和输出操作。但是在RTL设计中,必须设计接口来执行这些输入和输出操作,并且通常使用特定的I / O(输入-输出)协议进行操作。有关更多信息,请参考《Vivado Design Suite用户指南:高级综合(UG902)》中的“Ch.1 Manage Interface” 。(推荐参考:对ug902中manage interface部分的优质翻译)
INTERFACE
pragma指定如何在接口合成期间依据函数定义创建RTL端口。
RTL实现中的端口派生自:
Function-level protocols(函数层级的协议)也称为block-level I/O protocols(块级I/O协议),用于提供信号来控制函数何时开始操作,并指示函数操作何时结束、空闲和准备好接受新的输入。函数级协议的实现:
ap_ctrl_none
, ap_ctrl_hs
或ap_ctrl_chain
。其中的 ap_ctrl_hs
是默认的块级I / O协议。port-level (I/O) interface protocol(端口级I / O接口协议):可以为每个函数参数指定port-level (I/O) interface protocol(端口级I / O接口协议),如有效握手(ap_vld
)或确认握手(ap_ack
)。如果函数会返回一个值,则为顶层函数和函数返回中的每个参数创建端口级I/O接口协议。创建的默认I/O协议取决于C参数的类型。在使用块级IO协议启动块的操作后,使用端口级IO协议对数据进行序列输入和输出。
如果访问了全局变量,但所有读和写操作都是design的本地操作,即是在design中创建资源,那么在RTL中不需要I/O端口。如果全局变量是外部源或地址,则以类似的方式将其接口指定为标准函数参数。参见下面的示例。
当INTERFACE
pragma用于子函数时,只能使用register
选项。子函数不支持< mode>选项。
提示:Vivado HLS自动确定任何子函数使用的I/O协议。除了指定端口是否寄存外,您无法控制这些端口。
将pragma放在函数内。
#pragma HLS interface port= bundle= \
register register_mode= depth= offset= \
clock= name= \
num_read_outstanding= num_write_outstanding= \
max_read_burst_length= max_write_burst_length=
其中各部分含义:
< mode>:为函数参数、函数使用的全局变量或block-level control protocols指定接口协议模式。有关这些不同模式的详细描述,请参阅Vivado Design Suite用户指南中的“界面综合参考”:高级综合(UG902)。模式可以指定为以下方式之一:
ap_none
:没有协议。接口是一个数据端口。
ap_stable
:没有协议。接口是一个数据端口。Vivado HLS假设数据端口在重置后总是稳定的,这允许内部优化来删除不必要的寄存器。(这个没懂什么意思,打算再去看看ug902)
ap_vld
:(valid)实现一个与数据端口相关联的端口,以指示数据何时可供读写。
ap_ack
:(acknowledge)实现一个与数据端口相关联的端口,以确认数据已被读写。
ap_hs
:实现与数据端口关联的valid端口和acknowledge端口。以提供双向握手信号,指示数据何时对读写有效,以及确认数据已被读写。
ap_ovld
:实现与输出数据端口关联的valid端口,以指示数据何时可以读写。
IMPORTANT!: Vivado HLS使用模式ap_none实现输入参数或任何读/写参数的输入一半。
ap_fifo:
使用标准的FIFO接口实现端口。使用数据输入和输出端口以及相关的active-Low FIFO空端口和满端口。(英文没读懂,大致意思就是为流水型的数组数组接口额外配置了FIFO模块)
Note:只能在读参数或写参数上使用此接口。ap_fifo模式不支持双向读/写参数。
ap_bus
:实现指针和按引用传递端口作为总线接口。
ap_memory:
将数组参数实现为标准RAM接口。如果在Vivado IP integrator中使用RTL设计,则内存接口将显示为离散的端口。
bram:
将数组参数实现为标准RAM接口。如果在Vivado IP integrator中使用RTL设计,那么内存接口将作为单个端口出现。
axis:
将所有端口实现为一个AXI4-Stream接口。
s_axilite:
将所有端口实现为一个AXI4-Lite接口。Vivado HLS在导出RTL过程中生成一组相关的C驱动程序文件。
m_axi:
实现所有端口作为一个AXI4接口。可以使用config_interface命令指定32位(默认)或64位地址端口,并控制任何地址偏移量。
(AXI的我都不懂,需要看ug902)
ap_ctrl_none:
没有块级I/O协议。
注意:使用ap_ctrl_none模式可能会阻止使用C/RTL co-simulation 验证设计。
ap_ctrl_hs:
实现一组块级控制端口,以启动设计操作,并指示设计何时空闲、完成和准备好接受新的输入数据。
注意:ap_ctrl_hs模式是默认的块级I/O协议。
ap_ctrl_chain:
实现一组块级控制端口,以启动设计操作、继续操作,并指示设计何时空闲、完成和准备好接受新的输入数据。注意:(和ap_ctrl_hs的区别)ap_ctrl_chain接口模式类似于ap_ctrl_hs,但是它提供了一个额外的输入信号ap_continue来apply back pressure。Xilinx建议在将Vivado HLS块链接在一起时使用ap_ctrl_chain块级I/O协议。
port=< name>:指定接口pragma应用到的函数参数、函数返回值或全局变量的名称。
提示:可以将块级I/O协议(ap_ctrl_none、ap_ctrl_hs或ap_ctrl_chain)分配给函数返回值的端口,如:
#pragma HLS INTERFACE ap_ctrl_none port = return
bundle=< string>:将函数参数分组到AXI接口端口。默认情况下,Vivado HLS将指定为AXI4-Lite (s_axilite)接口的所有函数参数组到单个AXI4-Lite端口。类似地,所有指定为AXI4 (m_axi)接口的函数参数都被分组到一个AXI4端口中。该选项将具有相同bundle=< string>的所有接口端口显式地分组到相同的AXI接口端口中,并将RTL端口命名为< string>指定的值。
register:一个可选的关键字,用于寄存信号和任何相关协议信号,并使信号至少持续到函数执行的最后一个周期。此选项适用于以下界面模式:
提示:config_interface命令的-register_io选项可以全局控制寄存所有顶层函数的输入/输出。有关更多信息,请参阅Vivado Design Suite用户指南:高级合成(UG902)。
register_mode=
depth=< int>:指定testbench要处理的最大样本数目。此设置指示Vivado HLS为RTL co-simulation创建的verification adapter 中所需的FIFO的最大尺寸。提示:虽然深度通常是一个选项,但是对于m_axi接口来说它是必需的。
offset=< string>:控制AXI4- lite (s_axilite)和AXI4 (m_axi)接口中的地址偏移量。
对于s_axilite接口,
指定寄存器map中的地址。
对于m_axi接口,
指定了以下值:
direct
:生成一个标量输入偏移端口。
slave
:生成一个偏移端口,并自动将其映射到AXI4-Lite从接口。
off
:不生成偏移端口。
提示:config_interface命令的-m_axi_offset选项全局控制了设计中所有M_AXI接口的偏移端口。
clock=< name>:是可选的,只用于s_axilite模式。这定义了接口要使用的时钟信号。默认情况下,axis - lite接口时钟与系统时钟相同。此选项用于为axis - lite (s_axilite)接口指定单独的时钟。
提示:如果使用bundle选项将多个顶级函数参数分组到一个axis - lite接口中,那么只需要在一个bundle成员上指定时钟选项。
num_read_outstanding=:对于AXI4 (m_axi)接口,这个选项指定在设计停止之前,在没有响应的情况下,可以向AXI4总线发出多少读取请求。这显示了设计之中的内部存储——一个FIFO的大小:num_read_outstanding*max_read_burst_length*word_size
num_write_outstanding=:对于AXI4 (m_axi)接口,这个选项指定在设计停止之前,在没有响应的情况下,可以向AXI4总线发出多少写请求。这显示了设计之中的内部存储——一个FIFO的大小:num_write_outstanding*max_write_burst_length*word_size
。
max_read_burst_length=:对于AXI4 (m_axi)接口,这个选项指定了在突发传输期间所读取的数据值的最大的数量。
max_write_burst_length=:对于AXI4 (m_axi)接口,这个选项指定在突发传输期间写入的数据值的最大数量。
name=:此选项用于根据您自己的意愿重命名端口。生成的RTL端口将使用这个名称。
在本例中,两个函数参数都是使用AXI4-Stream接口实现的:
void example(int A[50], int B[50]) {
//Set the HLS native interface types
#pragma HLS INTERFACE axis port=A
#pragma HLS INTERFACE axis port=B
int i;
for(i = 0; i < 50; i++){
B[i] = A[i] + 5;
}
}
下面关闭块级I/O协议,并赋给函数返回值:
#pragma HLS interface ap_ctrl_none port=return
函数参数InData被指定为使用ap_vld接口,并且还表明输入应该被寄存:
#pragma HLS interface ap_vld register port=InData
此示例定义了顶级transpose函数的端口的接口标准。注意使用bundle=选项对信号进行分组。
// TOP LEVEL - TRANSPOSE
void transpose(int* input, int* output) {
#pragma HLS INTERFACE m_axi port=input offset=slave bundle=gmem0
#pragma HLS INTERFACE m_axi port=output offset=slave bundle=gmem1
#pragma HLS INTERFACE s_axilite port=input bundle=control
#pragma HLS INTERFACE s_axilite port=output bundle=control
#pragma HLS INTERFACE s_axilite port=return bundle=control
#pragma HLS dataflow