Bootstrap

pragma HLS stream语法

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

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

如果存储在数组中的数据是按顺序使用或产生的,则更有效的通信机制是使用stream pragma指定的流数据,其中使用FIFOs而不是ram。
重要!:当顶级函数的参数指定为接口类型ap_fifo时,该数组自动实现为流格式
(即,用dataflow优化,数组存取使用RAM pingpong buffer 实现,用stream优化,数组存取使用FIFOs实现)

语法

将C源代码中的pragma放在所需位置的边界内。

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

其中:

  • depth=<int>:只适用于数据流通道中的数组流。默认情况下,在RTL中实现的FIFO的深度与C代码中指定的数组大小相同。这个选项允许您修改FIFO的大小并指定不同的深度。
    当数组在数据流区域中实现时,通常使用depth=选项来减小FIFO的大小。例如,在一个数据流区域中,当所有循环和函数都以II=1的速率处理数据时,就不需要一个大型FIFO,因为数据是在每个时钟周期中产生和消耗的。在这种情况下,可以使用depth=选项将FIFO大小减少到1,从而大大减少RTL设计的面积。
    提示:config_dataflow -depth命令能够流化一个数据流区域中的所有数组。这里指定的depth=选项将覆盖指定变量的config_dataflow命令。

FIFO深度的含义[1]
FIFO的宽度:也就是英文资料里常看到的THE WIDTH,它只的是FIFO一次读写操作的数据位,就像MCU有8位和16位,ARM 32位等等,FIFO的宽度在单片成品IC中是固定的,也有可选择的,如果用FPGA自己实现一个FIFO,其数据位,也就是宽度是可以自己定义的。
FIFO的深度:THE DEEPTH,它指的是FIFO可以存储多少个N位的数据(如果宽度为N)。如一个8位的FIFO,若深度为8,它可以存储8个8位的数据,深度为12 ,就可以存储12个8位的数据,FIFO的深度可大可小,个人认为FIFO深度的计算并无一个固定的公式。在FIFO实际工作中,其数据的满/空标志可以控制数据的继续写入或读出。在一个具体的应用中也不可能由一些参数算数精确的所需FIFO深度为多少,这在写速度大于读速度的理想状态下是可行的,但在实际中用到的FIFO深度往往要大于计算值。一般来说根据电路的具体情况,在兼顾系统性能和FIFO成本的情况下估算一个大概的宽度和深度就可以了。而对于写速度慢于读速度的应用,FIFO的深度要根据读出的数据结构和读出数据的由那些具体的要求来确定。

  • dim=<int>:指定要流化的数组的维度。默认是维度1。指定为从0到N的整数,用于具有N维数的数组。
  • off:禁用流数据。只适用于数据流通道中的数组流
    提示:config_dataflow -default_channel fifo命令全局暗示了对设计中所有数组上使用stream pragma。这里指定的off选项会覆盖指定变量的config_dataflow命令,并恢复使用基于RAM pingpong buffer通道的默认值。

例子1

下面的例子指定数组A[10]为流,并实现为FIFO:

#pragma HLS STREAM variable=A

例子2

#pragma HLS STREAM variable=B depth=12

例子3

在这个例子中,假设config_dataflow是启用的,则off命令覆盖config_dataflow设置,数组C是禁用stream的。

#pragma HLS STREAM variable=C off

在网络之中的应用例子

void DoCompute(ap_uint<64> * in, ap_uint<64> * out, const unsigned int numReps) {
#pragma HLS DATAFLOW

	stream<ap_uint<64> > inter0("DoCompute.inter0"); //文件中DoCompute.inter0的数组
	stream<ap_uint<192> > inter0_1("DoCompute.inter0_1");
	stream<ap_uint<24> > inter0_2("DoCompute.inter0_2");
#pragma HLS STREAM variable=inter0_2 depth=128 //stream处理,数组深度(大小)是128
	stream<ap_uint<64> > inter1("DoCompute.inter1");
#pragma HLS STREAM variable=inter1 depth=128
	stream<ap_uint<64> > inter2("DoCompute.inter2");
	stream<ap_uint<64> > inter3("DoCompute.inter3");
#pragma HLS STREAM variable=inter3 depth=128
	stream<ap_uint<128> > inter4("DoCompute.inter4");
#pragma HLS STREAM variable=inter4 depth=128
	stream<ap_uint<128> > inter5("DoCompute.inter5");
	stream<ap_uint<128> > inter6("DoCompute.inter6");
#pragma HLS STREAM variable=inter6 depth=81
	stream<ap_uint<256> > inter7("DoCompute.inter7");
#pragma HLS STREAM variable=inter7 depth=1
	stream<ap_uint<256> > inter8("DoCompute.inter8");
#pragma HLS STREAM variable=inter8 depth=1
	stream<ap_uint<64> > inter9("DoCompute.inter9");
#pragma HLS STREAM variable=inter9 depth=128
	stream<ap_uint<64> > inter10("DoCompute.inter10");
#pragma HLS STREAM variable=inter10 depth=3
	stream<ap_uint<64> > memOutStrm("DoCompute.memOutStrm");

参考:
[1]深入理解FIFO(包含有FIFO深度的解释)

;