HLS pragma


HLS Pragmas

Vivado HLS Pragmas by Type

TypeAttributes
1 Kernel Optimization• pragma HLS allocation
• pragma HLS clock
• pragma HLS expression_balance
• pragma HLS latency
• pragma HLS reset
• pragma HLS resource
• pragma HLS top
2 Function Inlining• pragma HLS inline
• pragma HLS function_instantiate
3 Interface Synthesis• pragma HLS interface
• pragma HLS protocol
4 Task-level Pipeline• pragma HLS dataflow
• pragma HLS stream
5 Pipeline• pragma HLS pipeline
• pragma HLS occurrence
6 Loop Unrolling• pragma HLS unroll
• pragma HLS dependence
7 Loop Optimization• pragma HLS loop_flatten
• pragma HLS loop_merge
• pragma HLS loop_tripcount
8 Array Optimization• pragma HLS array_map
• pragma HLS array_partition
• pragma HLS array_reshape
9 Structure Packing• pragma HLS data_pack

1. Kernel Optimization

1.1 pragma HLS allocation

1.2 pragma HLS clock

1.3 pragma HLS expression_balance

1.4 pragma HLS latency

1.5 pragma HLS reset

1.6 pragma HLS resource

1.7 pragma HLS top

2. Function Inlining

• pragma HLS inline
• pragma HLS function_instantiate

2.1 pragma HLS inline

描述
内联一个函数,删除所有的函数层次结构。用于跨函数边界进行逻辑优化,并通过减少函数调用开销来改善延迟/间隔。
删除层次结构中作为单独实体的函数。内联之后,该函数将被溶解到调用函数中,并且不再作为RTL中单独的层次结构出现。在某些情况下,内联一个函数可以使函数内的操作与周围的操作更有效地共享和优化。内联函数不能共享?。这可能会增加实现RTL所需的区域。
INLINE pragma 的作用域取决于它的指定方式

  • INLINE: 没有参数,pragma意味着它所指定的函数应该内联到任何调用函数或区域。
  • INLINE OFF: 指定在中指定的函数不应向上内联到任何调用函数或区域中。这将禁用指定函数的内联,该函数本可以自动内联,也可以作为区域或递归的一部分内联。
  • INLINE REGION: 这将把pragma应用于它所赋值的区域或函数体。它向下应用,内联区域或函数的内容,但不递归地在层次结构中内联。
  • INLINE RECURSIVE: pragma应用于它所赋值的区域或函数体。它向下应用,递归地内联区域或函数的内容。
    默认情况下,内联只在函数层次结构的下一层执行,而不是子函数。然而,recursive选项允许您通过层次结构的级别指定内联。

语法
#pragma HLS inline <region | recursive | off>
选项

  • region:可选地指定指定区域内(或包含在函数体内)的所有函数内联,适用于该区域的范围。
  • recursive:默认情况下,只执行一级函数内联,指定函数中的函数不内联。recursive选项在指定的函数或区域内递归地内联所有函数。
  • off: 禁用函数内联,以防止指定的函数内联。例如,如果在函数中指定了recursive,在其他所有函数都内联的情况下,此选项可以防止指定的被调用函数内内联。

TIP:Vivado HLS自动内联小函数,可以使用INLINE pragma与off选项可用于防止这种自动内联。

inline pragma应用于不同的范围,
INLINE指令删除函数边界。这可用于将逻辑或循环提升到一个层次结构。 通过将逻辑包含在函数上方的函数中来管理函数中的逻辑可能更有效, 并将循环合并到它们上面的函数中,其中DATAFLOW优化可用于同时执行所有循环而无需中间子函数调用的开销。 这可能会带来更高性能的设计。

2.2 pragma HLS function_instantiate

3. Interface Synthesis

3.1 pragma HLS interface

根据函数描述,在接口综合期间指定如何创建RTL端口。

函数级协议(也称为块级I / O协议)提供控制信号 : 控制函数的开始,结束,处于空闲状态并为新输入做好准备。 函数级别协议的实现:

  • 由值ap_ctrl_none,ap_ctrl_hs或ap_ctrl_chain指定。 ap_ctrl_hs块级I / O协议是默认协议。
  • 与函数名称关联。

可以将每个函数参数指定为具有其自己的端口级(I / O)接口协议,例如有效握手(ap_vld)或确认握手(ap_ack)。 创建的默认I / O协议取决于C参数的类型。 在使用块级协议启动块的操作之后,使用端口级IO协议对数据进出块进行排序。

每个函数参数可以指定为具有自己的端口级(I/O)接口协议,如有效握手(ap_vld)或应答握手(ap_ack)。将为顶层函数中的每个参数和函数返回值创建端口级接口协议。创建的默认I/O协议取决于C参数的类型。使用块级协议启动块的操作后,使用端口级IO协议对数据进行序列输入和输出块。

?如果访问了全局变量,但所有读和写操作都是设计的本地操作,则在设计中创建资源。在RTL中不需要I/O端口。如果期望全局变量是外部源或目标,则以类似的方式将其接口指定为标准函数参数。参见下面的示例。

当接口pragma用于子函数时,只能使用register选项。<mode> 选项不支持子函数。
提示:Vivado HLS自动确定任何子函数使用的I/O协议。除可指定端口是否寄存外,无法控制这些端口。

语法

#pragma HLS interface <mode> port=<name> bundle=<string> \
register register_mode=<mode> depth=<int> offset=<string> \
clock=<string> name=<string> \
num_read_outstanding=<int> num_write_outstanding=<int> \
max_read_burst_length=<int> max_write_burst_length=<int>

-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)

  • <mode>: 指定接口协议模式 (函数参数、全局变量,块级控制协议)

    • ap_none: No protocol. The interface is a data port.
    • ap_stable: No protocol. The interface is a data port. Vivado HLS 假定数据端口复位后始终处于稳定状态, 这样即可支持内部最优化移除不必要的寄存器。
    • ap_vld: Implements the data port with an associated valid port to indicate when the data is valid for reading or writing.
    • ap_ack: Implements the data port with an associated acknowledge port to acknowledge that the data was read or written.
    • ap_hs: Implements the data port with associated valid and acknowledge ports to provide a two-way handshake to indicate when the data is valid for reading and writing and to acknowledge that the data was read or written.
    • ap_ovld: Implements the output data port with an associated valid port to indicate when the data is valid for reading or writing.
      IMPORTANT!: Vivado HLS 通过 ap_none 模式来实现输入实参或任意读取/写入实参的输入部分
    • ap_fifo: Implements the port with a standard FIFO interface using data input and output ports with associated active-Low FIFO empty and full ports.
    • Note: 仅限对读取实参和写入实参使用该接口。 ap_fifo 模式不支持双向读写实参。
    • ap_bus: Implements pointer and pass-by-reference ports as a bus interface.用于实现指针和按引用传递端口(作为总线接口)
    • ap_memory: Implements array arguments as a standard RAM interface. If you use the RTL design in Vivado IP integrator, the memory interface appears as discrete ports.
    • bram: Implements array arguments as a standard RAM interface. If you use the RTL design in Vivado IP integrator, the memory interface appears as a single port.
    • axis: Implements all ports as an AXI4-Stream interface.
    • s_axilite: 将所有端口实现为AXI4-Lite接口。 Vivado HLS在“导出RTL”过程中会生成一组关联的C驱动程序文件。
    • m_axi: 将所有端口实现为一个AXI4接口。可以使用config_interface命令指定32位(默认)或64位地址端口,并控制任何地址偏移量
    • ap_ctrl_none: 无块级 I/O 协议.
    • Note: 使用ap_ctrl_none模式可能会阻止使用C / RTL协同仿真功能验证设计.
    • ap_ctrl_hs: 实现一组块级控制端口,以start 设计操作,并指示设计何时idle、done和ready 接受新的输入数据。
      Note: The ap_ctrl_hs 是默认的块级I/O协议。.
    • ap_ctrl_chain: ap_ctrl_hs上增加continue 。
      Note: ap_ctrl_chain模式类似于ap_ctrl_hs,额外提供了ap_continue信号来施加反压。 在将Vivado HLS块链接在一起时,Xilinx建议使用ap_ctrl_chain块级I / O协议
  • port=<name>:指定INTERFACE pragma应用于的函数参数,函数返回或全局变量的名称
    TIP: 可以将块级I / O协议(ap_ctrl_none,ap_ctrl_hs或ap_ctrl_chain)分配给函数返回值的端口。

  • bundle = <string>:将函数参数分组到AXI接口端口中。 默认,Vivado HLS将指定为AXI4-Lite(s_axilite)接口的所有函数参数分组为单个AXI4-Lite端口。 同样,所有指定为AXI4(m_axi)接口的函数参数都被分组到单个AXI4端口中。 该选项将所有具有相同bundle = <string> 的接口端口显式分组为同一AXI interface 端口,并将RTL端口命名为<string> 的值。

  • register : 可选的,用于寄存信号和任何相关协议信号,并使信号持续到至少函数执行的最后一个周期。 此选项适用于以下接口模式:

    • ap_none
    • ap_ack
    • ap_vld
    • ap_ovld
    • ap_hs
    • ap_stable
    • axis
    • s_axilite
      TIP: config_interface命令的-register_io选项可以全局控制在顶部函数上寄存所有输入/输出。
  • register_mode = <forward | reverse | both | off>:与register一起使用,此选项指定是否将寄存器放置在forward 正向路径(TDATA和TVALID),reverse 反向路径(TREADY),两个路径(TDATA,TVALID和TREADY)上,或者是否没有端口信号要寄存(关闭)。 默认的register_mode为both。 AXI-Stream侧通道信号被认为是数据信号,当寄存TDATA时便被注册。

  • depth= <int> : 指定测试台要处理的最大样本数。 此设置指示Vivado HLS为 RTL co-simulation创建的验证适配器中所需的FIFO的最大大小。?
    TIP: 虽然depth通常是一个选项,但对m_axi接口是必需的。

  • offset=<string> :控制AXI4- lite (s_axilite)和AXI4 (m_axi)接口中的地址偏移量。

    • 对于s_axilite接口,指定寄存器映射中的地址。
    • 对于m_axi接口,指定了以下值:
      • direct:生成一个标量输入偏移端口。
      • slave:生成一个偏移端口,并自动将其映射到AXI4-Lite从接口。
      • off:不生成偏移端口。
        提示:config_interface命令的-m_axi_offset选项全局控制设计中所有M_AXI接口的偏移端口。
  • clock = <name>:(可选)仅为接口模式s_axilite指定。 这定义了用于接口的时钟信号。 默认情况下,AXI-Lite接口时钟与系统时钟相同。 该选项用于为AXI-Lite(s_axilite)接口指定单独的时钟。
    TIP: 如果使用bundle选项将多个顶层函数参数分组到单个AXI-Lite接口中,则只需要在其中一个bundle成员上指定clock选项。

  • num_read_outstanding=<int>: For AXI4 (m_axi) interfaces, this option specifies how many read requests can be made to the AXI4 bus, without a response, before the design stalls. This implies internal storage in the design, a FIFO of size: num_read_outstanding*max_read_burst_length*word_size.

  • num_write_outstanding=<int>:
    对于 AXI4(m_axi)接口,此选项指定在设计停止之前,可以在没有响应的情况下向 AXI4总线发出多少写请求。这意味着设计中的内部存储FIFO大小为:
    num_write_outstanding*max_write_burst_length*word_size

  • max_read_burst_length=<int>: 对于AXI4 (m_axi)接口,这个选项指定在突发传输期间读取的数据值的最大数量。

  • max_write_burst_length=<int>: 对于AXI4(m_axi)接口,此选项指定在突发传输期间写入的最大数据值数量

  • name = <string>:此选项用于重命名端口。 生成的RTL端口将使用此名称。

Example 1
In this example, both function arguments are implemented using an AXI4-Stream interface:
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;
  }
}

Example 2
The following turns off block-level I/O protocols, and is assigned to the function return value:
#pragma HLS interface ap_ctrl_none port=return

The function argument InData is specified to use the ap_vld interface, and also indicates the input should be registered:
#pragma HLS interface ap_vld register port=InData

This exposes the global variable lookup_table as a port on the RTL design, with an ap_memory interface:
#pragma HLS interface ap_memory port=lookup_table

Example 3
This example defines the INTERFACE standards for the ports of the top-level "transpose" function. Notice the use of the bundle= option to group signals.

// 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

3.2 pragma HLS protocol

PROTOCOL将代码的一个区域指定为协议区域,除非在代码中明确指定,否则Vivado HLS不会在其中插入时钟操作。 协议区域可用于手动指定接口协议,以确保最终设计可以连接到具有相同I / O协议的其他硬件模块。

Vivado HLS不会在操作之间插入任何时钟,包括从函数参数读取或写入函数参数的时钟,除非在代码中明确指定。 因此,在RTL中遵循读取和写入的顺序。

可以指定时钟操作:

  • In C by using an ap_wait() statement (include ap_utils.h).
  • In C++ and SystemC designs by using the wait() statement (include systemc.h).

ap_wait和wait语句分别对C和C ++设计的仿真没有影响。 它们仅由Vivado HLS解释。
To create a region of C code:

  1. Enclose the region in braces, {},
  2. Optionally name it to provide an identifier.

For example, the following defines a region called io_section:
io_section:{

}
语法
#pragma HLS protocol <floating | fixed>

  • floating :协议模式,允许协议区域外的语句与最终RTL中协议区域内的语句重叠。 协议区域内的代码保持周期精确,但是其他操作可以同时发生。 这是默认协议模式。
  • fixed : 协议模式,可确保协议区域内部或外部的语句不重叠
    IMPORTANT!: 如果没有指定协议模式,则默认为浮动模式。
io_section:{
  #pragma HLS protocol fixed
  ...
}

4. Task-level Pipeline

4.1 pragma HLS stream

描述

在使用DATAFLOW优化时,将特定数组实现为FIFO或RAM存储通道。 STREAM 指定将特定存储通道实现为具有可选特定深度的FIFO。

默认情况下,数组变量实现为RAM:

  • 顶层函数的数组参数实现为RAM接口端口。
  • 通用数组被实现为用于读写访问的RAM。
  • 在涉及DATAFLOW优化的子函数中,数组参数是使用RAM pingpong缓冲区通道实现的。
  • 涉及基于循环的数据流优化的数组被实现为RAM pingpong缓冲通道。

当以顺序方式使用或产生数组中的数据时,更有效的通信机制是使用STREAM pragma指定的流数据,使用FIFO代替RAM。
IMPORTANT!:当top-level function的参数指定为接口类型ap_fifo时,数组将自动实现为streaming。

语法
#pragma HLS stream variable=<variable> depth=<int> dim=<int> off

Option

  • variable= <variable>:指定要实现为流接口的数组的名称。
  • depth=<int>:仅与数据流通道中的数组流相关。默认情况下,RTL中实现的FIFO的深度与C代码中指定的数组大小相同。此选项允许修改FIFO的大小并指定不同的深度。
    当数组在数据流区域中实现时,通常使用depth=选项来减小FIFO的大小。例如,在一个数据流区域中,当所有循环和函数都以II=1的速率处理数据时,就不需要大型FIFO,因为数据是在每个时钟周期中产生和使用的。在这种情况下,可以使用depth=选项将FIFO大小减少到1,从而大大减少RTL设计的面积。
    TIP: config_dataflow -depth命令对DATAFLOW区域中的所有数组进行stream的功能。 此处指定的 *depth =*选项将覆盖已分配变量的config_dataflow命令。?
  • dim=<int>:指定要streamed的数组的维数。默认为维度1。指定为从0到N的整数,用于具有N个维度的数组。
  • off:禁用 streaming data。仅与dataflow通道中的 array streaming相关。
    TIP: The config_dataflow -default_channel fifo 全局命令意味着在设计中的所有数组上执行STREAM pragma。此处指定的off选项将覆盖已分配变量的config_dataflow命令,并恢复使用基于RAM pingpong 缓冲区的通道的默认设置。
    实例
    The following example specifies array A[10] to be streaming, and implemented as a FIFO:
#pragma HLS STREAM variable=A

In this example array B is set to streaming with a FIFO depth of 12:

#pragma HLS STREAM variable=B depth=12

Array C has streaming disabled. It is assumed to be enabled by config_dataflow in this example:

#pragma HLS STREAM variable=C off

4.2 pragma HLS dataflow

描述
DATAFLOW pragma支持任务级流水线,允许函数和循环在它们的操作中重叠,增加了RTL实现的并发性,并增加了设计的总体吞吐量。
在C描述中,所有操作都是按顺序执行的。在没有任何限制资源的指令(如pragma HLS分配)的情况下,Vivado®HLS寻求最小化延迟和提高并发性。但是,数据依赖关系可能会限制这一点。例如,访问数组的函数或循环必须在完成所有对数组的读/写访问之前完成。这可以防止下一个使用数据的函数或循环开始操作。DATAFLOW优化允许函数或循环中的操作在前一个函数或循环完成其所有操作之前开始操作。
Figure: DATAFLOW Pragma
当指定了DATAFLOW pragma时,Vivado HLS将分析顺序函数或循环之间的数据流,并创建通道(基于乒乓键或FIFOs),允许使用者函数或循环在生产者函数或循环完成之前开始操作。这允许函数或循环并行操作,从而减少延迟并提高RTL的吞吐量。

如果没有指定启动间隔(II:initiation interval从一个函数或循环的开始到下一个循环的周期数),Vivado HLS将尝试最小化启动间隔并在数据可用时立即启动操作。

提示:config_dataflow命令指定用于dataflow优化的默认存储通道和FIFO深度。更多信息参考(UG902)中的config_dataflow命令。

为了使DATAFLOW优化发挥作用,数据必须通过设计从一个任务流向下一个任务。以下编码风格阻止Vivado HLS执行DATAFLOW优化:
Single-producer-consumer违规

  • 绕过任务
  • 任务之间的反馈
  • 任务的条件执行
  • 具有多个退出条件的循环
    IMPORTANT!:如果存在这些编码样式,Vivado HLS将发出一条消息,并且不执行DATAFLOW优化。
    最后,DATAFLOW优化没有分层实现。如果子函数或循环包含可能受益于数据流优化的其他任务,则必须将优化应用于循环、子函数或内联子函数。

语法
#pragma HLS dataflow
实例

 wr_loop_j: for (int j = 0; j < TILE_PER_ROW; ++j) {
#pragma HLS DATAFLOW
            wr_buf_loop_m: for (int m = 0; m < TILE_HEIGHT; ++m) {
                wr_buf_loop_n: for (int n = 0; n < TILE_WIDTH; ++n) {
                #pragma HLS PIPELINE
                    // should burst TILE_WIDTH in WORD beat
                    outFifo >> tile[m][n];
                }
            }
            wr_loop_m: for (int m = 0; m < TILE_HEIGHT; ++m) {
                wr_loop_n: for (int n = 0; n < TILE_WIDTH; ++n) {
                #pragma HLS PIPELINE
                    outx[TILE_HEIGHT*TILE_PER_ROW*TILE_WIDTH*i+TILE_PER_ROW*TILE_WIDTH*m+TILE_WIDTH*j+n] = tile[m][n];
                }
            }

5. Pipeline

5.1 pragma HLS pipeline

PIPELINE pragma通过并发执行操作,减少了function or loop的启动间隔II。
PIPELINE的默认启动间隔II=1。
流水线循环允许循环的操作以并发的方式实现,如下图。(A)显示了默认的顺序操作,在执行最后一个输出写之前需要8个时钟周期。

已流水线化的函数与已流水线化的循环之间行为存在差异。
• 对于函数, 流水线将永久运行, 永不终止。
• 对于循环, 流水线将持续执行直至循环的所有迭代完成为止。
在下图中总结了行为差异
在这里插入图片描述
IMPORTANT!:依赖关系会阻止循环流水线。可以使用DEPENDENCE pragma 来提供额外的信息,克服循环附带的依赖关系,并允许循环是流水线的(或间隔较低的流水线)。

如果Vivado HLS无法使用指定的II创建设计,则:

  • 发出一个警告。
  • 创建一个尽可能低的II的设计。

可以使用警告消息分析此设计,确定采取哪些措施来创建满足所需II的设计。

语法
将pragma放在函数或循环体中。

	#pragma HLS pipeline II=<int> enable_flush rewind

option

  • II=<int>: 指定期望pipeline的启动时间间隔。根据数据依赖关系,实际II可能更大。默认II=1。
  • enable_flush: 可选的,仅支持流水线函数,不支持流水线循环。实现在以下情况下清空流水线: 当在流水线输入端有效的数据变为不活动时清空。
  • rewind: 可选的,仅适用于循环。支持回绕,或连续循环流水线操作 , 在循环迭代结尾与下一次迭代开始之间没有暂停。只有在顶级函数中有一个单独的循环(或完美循环嵌套)时, 回绕才有效。循环前的代码段:
    • 被视为初始化。
    • 在流水线中仅执行一次。
    • 不能包含任何条件运算 (if-else)

Example
In this example function foo is pipelined with an initiation interval of 1:

void foo { a, b, c, d} {
  #pragma HLS pipeline II=1
  ...
}

Note: The default value for II is 1, so II=1 is not required in this example.

PIPELINE VS UNROLL

PIPELINE: 通过允许同时执行循环或函数中的操作来缩短启动间隔。

  • 减少启动间隔
  • 同时执行

UNROLL: 展开for循环以创建多个独立操作.

  • 展开for循环
  • 多个独立操作

5.2 pragma HLS occurrence

对函数或循环进行流水线处理时,OCCURRENCE指定区域中的代码执行的频率低于外层函数或循环中的代码。 这允许执行频率较低的代码以较低的速率进行流水线化,并有可能在顶级流水线中共享。 要确定出现次数:

  • 循环迭代 N 次。
  • 循环的一部分受条件语句保护(由条件语句启用的), 并且仅执行 M 次, 其中 N 是 M 的整数倍。
  • 假设受条件保护的代码将执行 N/M 次。即条件代码的执行率比其余部分慢N/M倍。

例如,在执行10次的循环中,循环中的条件语句仅执行2次, occurrence of =5 (or 10/2)

  • 可以在外层较高速率的流水线中更好地共享。

标识某一区域, 在此区域中流水线化的函数和循环的II比外层函数或循环更长。

通过使用OCCURRENCE杂指令识别区域,可以以较高的启动间隔对该区域中的功能和循环进行管线传输,该启动间隔比封闭的功能或循环要慢。
语法

#pragma HLS occurrence cycle=<int>

cycle=<int>: Specifies the occurrence N/M, where:

  • N is the number of times the enclosing function or loop is executed .
  • M is the number of times the conditional region is executed.
    IMPORTANT!: N must be an integer multiple of M.
  • N是封闭函数或循环执行的次数。
  • M是条件区域执行的次数。

重要!N一定是M的整数倍
例子
在这个例子中,区域Cond_Region的occurrence为4(它的执行频率比包含它的周围代码低四倍)

Cond_Region: {
#pragma HLS occurrence cycle=4
...
}

6. Loop Unrolling

6.1 pragma HLS unroll

描述
展开循环体以创建多个独立副本。
默认情况下,C/C ++函数中的循环保持折叠的(rolled)状态。 循环折叠的(rolled)时,综合会创建一个迭代逻辑,RTL为循环的每次迭代依次执行此逻辑(复用逻辑)。使用UNROLL pragma,可以展开循环以增加数据访问和吞吐量。
完全或部分展开:
UNROLL pragma允许循环完全或部分展开。完全展开循环会在RTL中为每个循环迭代创建循环体的副本,因此整个循环可以并发运行。部分展开循环指定一个因子N,以创建循环体的N个副本,并相应地减少循环的迭代次数。完全展开循环,必须在编译时知道循环边界。对于部分展开是不需要的。
部分循环展开不需要N是最大循环迭代计数的整数因子。 Vivado HLS添加了退出检查,以确保部分展开的循环在功能上与原始循环相同。 例如,给出以下代码:

for(int i = 0; i < X; i++) {
	pragma HLS unroll factor=2
	a[i] = b[i] + c[i];
}
//循环展开2倍可以有效地将代码转换为以下代码,其中使用break构造以确保功能保持不变,并且循环在适当的点退出:
for(int i = 0; i < X; i += 2) {
	a[i] = b[i] + c[i];
	if (i+1 >= X) break;
	a[i+1] = b[i+1] + c[i+1];
}

因为最大迭代计数X是一个变量,Vivado HLS可能无法确定它的值,因此向部分展开的循环添加了退出检查和控制逻辑。但是,如果您知道指定的展开因子(本例中的2)是最大迭代计数X的整数因子,则skip_exit_check选项允许您删除退出检查和相关逻辑。这有助于最小化面积和简化控制逻辑。
TIP:当使用诸如DATA_PACK、ARRAY_PARTITION或ARRAY_RESHAPE这样的pragma让更多的数据在一个时钟周期内被访问时,Vivado HLS会unroll自动展开使用这些数据的任何循环,如果这样做可以提高吞吐量的话。循环可以完全或部分展开,以创建足够的硬件来在单个时钟周期中消耗额外的数据。该特性由config_unroll命令控制。参见(UG902)中的config_unroll。

使用unroll的情况:
流水线操作无法达到期望的II时,可能需要UNROLL指令。如果一个循环只能用II = 4进行流水线操作,它将限制系统中的其他循环和函数限制为II = 4。 在某些情况下,可能需要展开或部分展开循环以创建更多逻辑并消除潜在的瓶颈。如果循环只能达到II = 4,则将循环展开4倍会产生逻辑,该逻辑可以并行处理循环的四次迭代并实现II = 1。
语法
将编译指示放在循环体内的C / C ++源代码中
#pragma HLS unroll factor=<N> region skip_exit_check

  • factor=:指定一个非零整数,表示请求部分展开。指定循环体重复的次数,并相应地调整迭代信息。如果没有指定factor=,则循环将完全展开。
  • region:一个可选的关键字,它展开指定循环体(区域)内的所有循环,而不展开封闭循环enclosing loop本身。
  • skip_exit_check:一个可选关键字,仅当使用factor=指定部分展开时才适用。退出检查的消除取决于循环迭代计数是已知的还是未知的:
    *固定(已知)界限:如果迭代计数是因子的倍数,则不执行退出条件检查。如果迭代计数不是因子的整数倍,则工具:
    1,防止展开。
    2,发出警告,说明必须执行退出检查才能继续。
    *变量(未知)界限:退出条件检查被请求删除。你必须确保:
    1,变量边界是指定的展开因子的整数倍。
    2,实际上不需要exit check。

**Example **
Example 1: The following example fully unrolls loop_1 in function foo.

loop_1: for(int i = 0; i < N; i++) {
	#pragma HLS unroll
	a[i] = b[i] + c[i];
}

Example 2:
This example specifies an unroll factor of 4 to partially unroll loop_2 of function foo, and removes the exit check:

void foo (...) {
  int8 array1[M];
  int12 array2[N];
  ...
  loop_2: for(i=0;i<M;i++) {
    #pragma HLS unroll skip_exit_check factor=4
    array1[i] = ...;  
    array2[i] = ...;
    ...
  }
  ...
}

Example 3:
以下示例完全展开函数foo中loop_1内部的所有循环,但由于存在region关键字,因此无法完全展开loop_1本身

void foo(int data_in[N], int scale, int data_out1[N], int data_out2[N]) {
	int temp1[N];
	loop_1: for(int i = 0; i < N; i++) {  
		#pragma HLS unroll region
		temp1[i] = data_in[i] * scale;
		loop_2: for(int j = 0; j < N; j++) {
		    data_out1[j] = temp1[j] * 123;
		}
		loop_3: for(int k = 0; k < N; k++) {
		   data_out2[k] = temp1[k] * 456;
		}
	}
}

6.2 pragma HLS dependence

DEPENDENCE pragma用于提供额外的信息,这些信息可以克服循环进位 loop-carry 依赖,并允许循环是流水线的(或间隔较低的流水线)。
Vivado HLS自动检测依赖项:

  • 在循环内(loop-independent dependence),
  • 或在循环的不同迭代之间(loop-carry dependence)。

这些依赖关系会影响何时可以调度操作,特别是在函数和循环流水线期间。

  • Loop-independent dependence独立于循环的依赖关系: 在同一个循环迭代中访问相同的元素
for (i=0;i<N;i++) {
 A[i]=x;
 y=A[i];
}
  • Loop-carry dependence循环附带的依赖关系: 在不同的循环迭代中访问相同的元素
for (i=0;i<N;i++) {
 A[i]=A[i-1]*2;
}

在某些复杂的情况下,自动dependence 分析可能过于保守,无法过滤出错误的依赖。
在某些情况下,例如变量相关的数组索引,或者当需要执行外部要求时(例如,两个输入永远不会是同一索引),相关性分析可能过于保守。 DEPENDENCE pragma允许显式指定依赖关系并解决错误的依赖关系。
IMPORTANT!:指定一个假依赖项,而实际上该依赖项不是假的,可能导致不正确的硬件。在指定依赖项之前,确保它们是正确的(true或false)。
语法

#pragma HLS dependence variable=<variable> <class> \
<type> <direction> distance=<int> <dependent>
  • variable=< variable>
    (可选)指定要考虑依赖关系的变量。
    不能为(已与其他参数绑定在一个m_axi接口中)的函数参数指定依赖关系。这是函数中m_ax接口的默认配置。也不能为结构的元素指定依赖关系,除非该结构已被分解。
  • <_class>:(可选)指定变量的类别,在其中需要澄清依赖性。有效值包括数组或指针。
    TIP: <_class>和variable =不需要一起指定,因为可以在函数中指定变量或一类变量。
  • < type>: 有效值包括 intra or inter。指定依赖于:
    • intra:同一 loop iterations中的依赖。 当依赖项<_type>指定为intra且<_dependent>为false时,Vivado HLS可以在loop内自由移动操作,从而增加其移动性并可能改善性能或面积。 当<_dependent>指定为true时,必须按指定的顺序执行操作。
    • inter:不同 loop iterations之间的依赖。 这是默认的 < type>。 如果将依赖项< type>指定为inter,并且<_dependent>为false,则如果函数或循环已管道化,或者循环已展开或部分展开,则它允许Vivado HLS并行执行操作。< dependent>被指定为true情况时阻止此类并发操作。
  • 不同循环迭代之间的依赖关系。 这是默认的。 如果将依赖项指定为inter,并且为false,则如果函数或循环已管道化,循环已展开或部分展开,则允许HLS工具并行执行操作,并防止此类并发操作 当指定为true时。
  • < direction>:有效值包括RAW,WAR或WAW。 这仅与循环 loop-carry dependencies 有关,并指定依赖项的方向:
    RAW(写后读-真正的依赖性)写指令使用读指令使用的值。
    WAR(读后写-反相关)读取指令获得的值被写入指令覆盖。
    WAW(写后写-输出相关性)两个写指令以一定顺序写到同一位置。
  • distance=< int>: Specifies the inter-iteration distance for array access. Relevant only for loop-carry dependencies where dependence is set to true.
  • < dependent>: 指定依赖项需要强制(true)还是移除(false)。默认值为true。
    指定这个参数来指示依赖关系是true且需要强制执行,还是false且应该删除。如果未指定该值,该工具将返回未指定该值的警告,并假定该值为false。

Example 1
在下面的例子中,Vivado HLS不知道cols的值,并且保守地假设对buff_A[1][col]的写和对buff_A[1][col]的读之间总是存在依赖关系。在这样的算法中,cols不太可能是零,但是Vivado HLS不能对数据依赖关系做出假设。为了克服这个不足,您可以使用DEPENDENCE pragma来声明循环迭代之间不存在依赖关系(在本例中,对于buff_A和buff_B)。

void foo(int rows, int cols, ...)
  for (row = 0; row < rows + 1; row++) {
    for (col = 0; col < cols + 1; col++) {
      #pragma HLS PIPELINE II=1
      #pragma HLS dependence variable=buff_A inter false
      #pragma HLS dependence variable=buff_B inter false
      if (col < cols) {
      buff_A[2][col] = buff_A[1][col]; // read from buff_A[1][col]
      buff_A[1][col] = buff_A[0][col]; // write to buff_A[1][col]
      buff_B[1][col] = buff_B[0][col];
      temp = buff_A[0][col];
}

Example 2
Removes the dependence between Var1 in the same iterations of loop_1 in function foo.
#pragma HLS dependence variable=Var1 intra false
Example 3
定义函数foo在loop_2中对所有数组的依赖关系,以通知Vivado HLS在同一个循环迭代中,所有的读操作都必须在写操作(原始操作)之后进行。
#pragma HLS dependence array intra RAW true

7. Loop Optimization

7.1 pragma HLS loop_flatten

7.2 pragma HLS loop_merge

7.3 pragma HLS loop_tripcount

8. Array Optimization

array_map对数组在长度或位宽上重映射为长度更长或位宽更宽的数组。
array_partition将数组划分为更小数组。
array_reshape:具有以上两者功能

8.1 array_map

将多个小数组合成一个大数组,共享BRAM资源。

当设备支持时,每个数组被映射到块RAM或UltraRAM中。
FPGA提供的基本块RAM单元是18K。
如果许多小数组不使用完整的18K,那么更好地使用BRAM资源是将许多小数组映射到一个更大的数组中。

提示:如果块RAM大于18K,它们会自动映射为多个18K单元。
ARRAY_MAP pragma支持两种映射方法:

  • 水平映射Horizontal mapping:连接源数组来拼接成长度更长的新数组。从物理上讲,新数组被实现为包含多个元素的数组。
  • 垂直映射Vertical mapping:对源数组进行位拼接,新数组位宽是各个数组元素位宽之和。在物理上,新数组被实现为一个具有更大位宽的数组。

语法
#pragma HLS array_map variable=<name> instance=<instance> <mode> offset=<int>

  • variable :被合并的数组名
  • instance :合并后新数组名
  • <mode>:可选项 horizontal or vertical
    - 水平映射是默认模式,并将数组连接起来形成一个包含更多元素的新数组。
    - 垂直映射将数组连接起来,形成一个更大的位宽的新数组。
  • offset:仅用于水平类型映射。偏移量指定在将数组映射到新数组之前应用的偏移量。例如:
    - 数组变量的元素0映射到元素新的目标。
    - 其他元素映射到新数组的<int+1>, <int+2>…

IMPORTANT!:如果没有指定偏移量,Vivado HLS将自动计算所需的偏移量,以避免数组元素重叠。

**Example **

Example 1
Arrays array1 and array2 in function foo are mapped into a single array, specified as array3 in the following example:

void foo (...) {
int8 array1[M];
int12 array2[N];
#pragma HLS ARRAY_MAP variable=array1 instance=array3 horizontal
#pragma HLS ARRAY_MAP variable=array2 instance=array3 horizontal
...
loop_1: for(i=0;i<M;i++) {
array1[i] = ...;
array2[i] = ...;
...
}
...
}
Example 2
This example provides a horizontal mapping of array A[10] and array B[15] in function foo into a single new array AB[25].
Element AB[0] will be the same as A[0].
Element AB[10] will be the same as B[0] because no offset= option is specified.
The bit-width of array AB[25] will be the maximum bit-width of either A[10] or B[15].
#pragma HLS array_map variable=A instance=AB horizontal
#pragma HLS array_map variable=B instance=AB horizontal
Example 3
The following example performs a vertical concatenation of arrays C and D into a new array CD, with the bit-width of C and D combined. The number of elements in CD is the maximum of the original arrays, C or D:

#pragma HLS array_map variable=C instance=CD vertical
#pragma HLS array_map variable=D instance=CD vertical

8.2 array_partition

描述
将数组划分为更小的数组或单个元素。
划分后:

  • RTL将具有多个小存储器或多个寄存器。
  • 有效地增加存储的读、写端口的数量。
  • 可能会提高设计的吞吐量。
  • 需要更多存储实例或寄存器。

语法
#pragma HLS array_partition variable=<name> <type> factor=<int> dim=<int>

选项

  • variable = <name>:数组名。
  • <type>:(可选)默认类型是complete。支持以下类型:
    - cyclic :循环分区将原数组的元素交叉放置在更小的数组中。例如,factor = 3:
    元素0被分配给第一个新数组。
    元素1被分配给第二个新数组。
    元素2被分配给第三个新数组。
    元素3再次分配给第一个新数组。依次循环
    - block:块分区从原始数组的连续块创建较小的数组。 这有效地将数组拆分为N个相等的块,其中factor=N。原始数组被分割成大小相等的块,这些块(新数组)由原始数组中连续的元素组成。
    - complete:完整分割将数组分解为单个元素。对于一维数组,这相当于将内存分解为单个的寄存器。这是<type>默认值。
  • factor=<int> :指定要创建的小数组的数目
  • dim=<_int>:指定要分区的多维数组的哪个维度。指定为一个从0到N的整数,对于一个有N维的数组:
    如果使用0值,多维数组的所有维都将使用指定的类型和因子选项进行分区。
    – 任何非零值只对指定的维度进行分区。例如,如果使用值1,则只对第一个维度进行分区。

IMPORTANT!:对于complete类型分区,不指定factor。对于block and cyclic分区,需要factor。
下图右侧一个连续的块代表一个数组。在接口中会用到cyclic。
在这里插入图片描述
在这里插入图片描述
Example

Example 1
This example partitions the 13 element array, AB[13], into four arrays using block partitioning:
#pragma HLS array_partition variable=AB block factor=4
TIP:
Because four is not an integer factor of 13:
Three of the new arrays have three elements each,
One array has four elements (AB[9:12]).

Example 2
This example partitions dimension two of the two-dimensional array, AB[6][4] into two new arrays of dimension [6][2]:
#pragma HLS array_partition variable=AB block factor=2 dim=2

Example 3
This example partitions the second dimension of the two-dimensional in_local array into individual elements.
int in_local[MAX_SIZE][MAX_DIM];
        #pragma HLS ARRAY_PARTITION variable=in_local complete dim=2    

8.3 array_reshape

ARRAY_RESHAPE 指令对数组进行分区并将已分区的元素重新组合到更宽的数组中。
ARRAY_RESHAPE结合了ARRAY_PARTITION的效果(将数组拆分成较小的数组)和垂直类型的ARRAY_MAP的效果(通过增加位宽连接数组的元素)。这减少了块RAM的消耗,同时提供了分区的主要好处:并行访问数据。这个pragma创建了一个元素更少但位宽更大的新数组,允许在一个时钟周期中访问更多数据。

void foo (...) {
	int array1[N];
	int array2[N];
	int array3[N];
	#pragma HLS ARRAY_RESHAPE variable=array1 block factor=2 dim=1
	#pragma HLS ARRAY_RESHAPE variable=array2 cycle factor=2 dim=1
	#pragma HLS ARRAY_RESHAPE variable=array3 complete dim=1
	...
}

在这里插入图片描述
如上图,与array_partition的图有区别。在于右侧的数组被组合为位宽更宽的数组。
语法

#pragma HLS array_reshape variable=\<name> \<type>  factor=\<int>  dim=\<int>

选项

  • <name> :指定要reshape的数组变量
  • <type> :可选地指定分区类型。默认类型是complete。支持以下类型
    - cyclic:通过交错原始数组中的元素来创建更小的数组。例如,如果使用factor=3,元素0被分配给第一个新数组,元素1被分配给第二个新数组,元素2被分配给第三个新数组,然后元素3被再次分配给第一个新数组。最终数组是新数组的垂直连接(单词连接,以创建更长的单词)到单个数组。
    - 块:块重塑从原始数组的连续块创建更小的数组。这有效地将数组分割为N个相等的块,其中N是factor=定义的整数,然后将这N个块合并为一个单词宽度N的数组。
    - 完成:完成重塑将数组分解为临时的单个元素,然后将它们重新组合成一个包含更宽单词的数组。对于一维数组,这相当于创建一个非常宽的寄存器(如果原始数组是N个元素的M位,那么结果就是一个N
    M位的寄存器)。这是数组重塑的默认类型
  • factor=<int>
  • dim=<int>

对于complete 的类型分区,不指定factor 。对于 block and cyclic,需要factor =。
Example

Example 1
Reshapes (partition and maps) an 8-bit array with 17 elements, AB[17], into a new 32-bit array with five elements using block mapping.

#pragma HLS array_reshape variable=AB block factor=4
TIP: factor=4 indicates that the array should be divided into four. So 17 elements is reshaped into an array of 5 elements, with four times the bit-width. In this case, the last element, AB[17], is mapped to the lower eight bits of the fifth element, and the rest of the fifth element is empty.
Example 2
Reshapes the two-dimensional array AB[6][4] into a new array of dimension [6][2], in which dimension 2 has twice the bit-width:

#pragma HLS array_reshape variable=AB block factor=2 dim=2
Example 3
Reshapes the three-dimensional 8-bit array, AB[4][2][2] in function foo, into a new single element array (a register), 128 bits wide (4*2*2*8):

#pragma HLS array_reshape variable=AB complete dim=0
TIP: dim=0 means to reshape all dimensions of the array.

loop_tripcount

描述
可以将TRIPCOUNT pragma应用于循环,以手动指定循环执行的迭代总数。
IMPORTANT!: TRIPCOUNT pragma仅用于分析,不影响综合的结果
Vivado®HLS报告每个循环的总延迟,即执行循环的所有迭代所需的时钟周期数。因此,循环延迟是循环迭代次数或循环次数的函数。
tripcount可以是一个常量。它可能依赖于循环表达式中使用的变量的值(例如,x<y),或者依赖于循环中使用的控制语句。在某些情况下,Vivado HLS不能确定tripcount,并且延迟未知。这包括用于确定旅行次数的变量为:

  • Input arguments, or
  • Variables calculated by dynamic operation.

在循环延迟未知或无法计算的情况下,TRIPCOUNT pragma允许您指定循环的最小和最大迭代。这使工具能够分析循环延迟如何影响报告中的总设计延迟,并帮助您确定适当的设计优化。max=:指定循环迭代的最大次数。
语法
#pragma HLS loop_tripcount min= max= avg=
max=:指定循环迭代的最大次数。
min=:指定循环迭代的最小数量。
avg=:指定循环迭代的平均次数。

resource

描述
RESOURCE 指定使用特定硬件资源(核心)用于在RTL中来实现变量(数组,算术运算或函数参数)。
当库中的多个核心可以实现该操作时,可以指定使用RESOURCE pragma使用哪个核心。要生成可用内核的列表,可以使用list_core命令。
TIP: 提示:list_core命令用于获取库中可用内核的详细信息。list_core只能在Vivado HLS Tcl命令接口中使用,Xilinx®设备必须使用set_part命令指定。如果没有选择设备,list_core命令没有任何效果。

例如,要指定要使用库中的哪个内存元素来实现数组,可以使用资源pragma。这使您可以控制数组是作为单个RAM实现还是作为双端口RAM实现。这种用法对于顶级函数接口上的数组非常重要,因为与数组关联的内存类型决定了RTL中所需的端口。
您可以使用latency=选项来指定核心的延迟。对于接口上的块ram, latency=选项允许您在接口上对芯片外的非标准SRAMs建模,例如支持延迟为2或3的SRAM。有关更多信息,请参见(UG902)中的Arrays on the Interface。对于内部操作,latency=选项允许使用更多的管道阶段来实现操作。这些附加的管道阶段可以帮助解决RTL合成期间的时间问题。
重要!:要使用latency=选项,操作必须有一个可用的multi-stage core。Vivado HLS为所有基本算术运算(加、减、乘、除)、所有浮点运算和所有块ram提供了一个multi-stage core。
Syntax
#pragma HLS resource variable= core=
latency=<int>
option:

  • variable=: 指定要分配资源的数组、算术运算或函数参数 。
  • core=: 指定库中定义的core。
  • latency=<int>: core的延迟.
    实例
    #pragma HLS RESOURCE variable=c latency=2
    #pragma HLS resource variable=coeffs core=RAM_1P

data_pack

将struct的数据字段打包为具有更宽字宽的单个标量,允许单个控制信号控制所有字段。

DATA PACK pragma用于将结构体struct的所有元素打包成单个宽向量以减少变量所需的内存,同时允许同时对结构体的所有成员进行读写。可以从struct字段的声明顺序推断出新宽字的位对齐。第一个字段在向量的LSB,最后一个元素与向量的MSB对齐。

如果结构体包含数组,则DATA_PACK与ARRAY_RESHAPE执行类似的操作,将重构的数组与struct中的其他元素组合。 在结构体内的所有数组都将被完全partitioned并reshaped 为宽标量,并与其他标量字段一起打包。 但是,不能使用DATA_PACK和ARRAY_PARTITION或ARRAY_RESHAPE对结构进行优化,因为这些编译指示是互斥的。

如果要用AXI4接口实现struct端口,应该考虑使用DATA PACK <byte pad>选项自动将结构的成员元素与8位边界对齐。AXI4-Stream协议要求IP的TDATA端口的宽度为8的倍数。如果定义的AXI4-Stream IP的TDATA端口宽度不是8的倍数,这违反了规范,因此,需要将TDATA的宽度整到字节的倍数。Refer to “Interface Synthesis and Structs” in Vivado Design Suite User Guide: High-Level Synthesis (UG902) for more information.

Syntax

#pragma HLS data_pack variable=<variable> instance=\<name> \<byte_pad>
  • variable=<variable>: 是要打包的变量.
  • instance=<name>: 打包后结果变量的名称。 如果未指定<name>,则使用输入<variable>。
  • <byte_pad>: (可选)指定是否在8位边界(8位,16位,24位…)上打包数据。 此选项支持的两个值是:
    • struct_level:首先打包整个struct,然后将其向上填充到下一个8位边界。

    • field_level:首先将结构的每个元素(字段)填充在8位边界上,然后打包该结构。

通常,通过考虑数据的原子性来确定在对齐字节边界之前(field_level)还是之后(struct_level)将数据的多个字段连接在一起。 原子信息是可以自己解释的数据,而非原子信息对于解释数据而言是不完整的。 例如,原子数据可以由浮点数中的所有信息位组成。 但是,仅浮点数中的指数位不是原子的。 将信息打包到TDATA中时,通常将数据的非原子位连接在一起(无论位宽如何),直到它们形成原子单元为止。 然后在必要时使用填充位将原子单位对齐到字节边界。

loop_flatten

LOOP_FLATTEN允许将嵌套循环折叠为单个循环。 这消除了循环转换开销并改善了延迟。 应用PIPELINE指令时,嵌套循环会自动展平
在RTL实现中,从外部循环到内部循环以及从内部循环到外部循环需要一个时钟周期。扁平化嵌套循环使它们可以作为单个循环进行优化。这样可以节省时钟周期,从而有可能进一步优化循环体逻辑。
将LOOP_FLATTEN pragma应用于循环层次结构中最内部循环的循环体。只有完全环和半完全环才能这样平展:

  • Perfect loop nests:
    1,仅最内部的循环具有循环主体内容。
    2,循环语句之间未指定逻辑。
    3,所有循环边界都是恒定的。

  • Semi-perfect loop nests:
    1,仅最内部的循环具有循环主体内容。
    2,循环语句之间未指定逻辑。
    3,最外面的循环界限可以是变量

  • Imperfect loop nests
    当内部循环具有可变范围(或循环主体不完全位于内部循环内部)时,请尝试重组代码,或在循环主体中展开循环以创建完美的循环嵌套。
    语法
    将pragma放在C源代码中嵌套循环的边界内。

    #pragma HLS loop_flatten off
    off:是一个可选关键字,用于防止发生展平。可以防止某些循环被展平,而指定位置中的所有其他循环都被展平。
    Note:存在LOOP_FLATTEN pragma将启用优化。

实例

Flattens loop_1 in function foo and all (perfect or semi-perfect) loops above it in the loop hierarchy, into a single loop. Place the pragma in the body of loop_1.
将函数foo中的loop_1平坦化,并将其在循环层次结构中位于其上方的所有(perfect or semi-perfect)循环平整为一个循环。 将pragma 放在loop_1的主体中。

void foo (num_samples, ...) {
  int i;
  ...
  loop_1: for(i=0;i< num_samples;i++) {
   #pragma HLS loop_flatten
   ...
    result = a + b;
  }
}

防止loop_1中的循环变平

//Prevents loop flattening in loop_1:
loop_1: for(i=0;i< num_samples;i++) {
   #pragma HLS loop_flatten off
   ...

9. Structure Packing

pragma HLS data_pack

作用对象:结构体
把结构体的数据字段打包到字宽更宽的单一标量中。
在该结构体内部声明的所有数组都将全部分区并重构为单一大宽度标量, 与其它标量字段封装在一起。
可根据结构体字段的声明顺序推断出生成的新字宽标量的位对齐方式。第一个字段占用该字词的最低有效位, 依此类
推, 直到映射完成所有字段为止。
注释: DATA_PACK 最优化不支持包含其它结构体的打包结构。

参考

UG1270
UG902 Vivado Design Suite User Guide: High-Level Synthesis

总结

  • IMPORTANT!:当top-level function的参数指定为接口类型ap_fifo时,数组将自动实现为streaming。
  • 当使用诸如DATA_PACK、ARRAY_PARTITION或ARRAY_RESHAPE这样的pragma让更多的数据在一个时钟周期内被访问时,Vivado HLS会unroll自动展开使用这些数据的任何循环,如果这样做可以提高吞吐量的话。此时不用再加入unroll
  • 提示:Vivado HLS自动确定任何子函数使用的I/O协议。除了指定端口是否注册外,无法控制这些端口。

  • 使用ap_ctrl_none模式可能会阻止使用C / RTL协同仿真功能验证设计。

  • Note: ap_ctrl_chain模式类似于ap_ctrl_hs,额外提供了ap_continue信号来施加反压。 在将Vivado HLS块链接在一起时,Xilinx建议使用ap_ctrl_chain块级I / O协议
    
  • 项目

    • 项目
      • 项目
  1. 项目1
  2. 项目2
  3. 项目3
  • 计划任务
  • 完成任务
  • 7
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值