HLS实践 - 06 - 优化设计(二)

简介: HLS实践 - 06 - 优化设计

流水操作整个函数


新建解决方案然后选择顶层的matrixmul标签添加PIPELINE指令,并移除Col中的流水操作,如下图所示:

image.png

添加完成后运行C综合,然后分析报告,进行对比流水内部循环和整个函数的区别。

image.png

该设计现在以更少的时钟完成,并且可以每 5 个时钟周期开始一个新的事务。 然而,由于设计中的所有环路都展开了,因此面积和资源大幅增加。流水线循环允许循环保持滚动,从而提供了控制区域的好方法。 流水线化整个函数时,函数中包含的所有循环都被展开,这是流水线化的要求。 流水线功能设计可以每 5 个时钟周期处理一组新的 9 个样本。 这超出了每个时钟 1 个样本的要求,因为高级综合的默认行为是生成具有最高性能的设计。

流水线整个函数产生的是最佳性能。 但是,如果它超过了所需的性能,则可能需要多个额外的指令来减慢设计速度。流水线循环为您提供了一种控制资源的简单方法,可选择部分展开设计以满足性能要求。

使用FIFO接口


完成对内部数据处理后,处理函数的接口。设计要求使用FIFO接口。现在进行新建解决方案,然后在a、b、res这三个数组进行设置使用FIFO接口。添加接口指令如下:

image.png

完成指令添加后点击运行C综合,此时无法正常综合,报错如下:

image.png

image.png

从图中的代码中,数组 res 按以下顺序执行写操作(MAT_B_COLS = MAT_B_ROWS = 3):

  • 在57行写入[0][0]
  • 在60行写入 [0][0]
  • 在60行写入 [0][0]
  • 在60行写入 [0][0]
  • 在第 57 行写入 [0][1](在索引 J 增加之后);
  • 在60行写入 [0][0]

对地址 [0][0] 的连续四次写入不构成流式访问模式 ; 这是随机访问。所以无法使用流接口。 C 代码的性质(指定对相同地址的多次访问)阻止了流接口的应用。在流接口中,必须按顺序访问这些值。

读取数组 a 和 b 存在类似的问题。 不可能使用 FIFO 接口通过编写的代码进行数据访问。 要使用 FIFO 接口,Vivado 高级综合中可用的优化指令是不够的,因为代码当前强制执行特定的读取和写入顺序。 进一步优化需要重写代码。

下图显示了之前的代码的数据IO访问模式。

image.png

由于变量 i、j 和 k 从 0 到 3 迭代,下半部分显示了读取 a、b 和写入 res 时生成的地址。 此外,在每个 Product 循环开始时, res 设置为零值。

对于具有顺序流访问的硬件设计,端口访问只能是以红色突出显示的那些。 对于读端口,数据必须在内部缓存,以确保设计不必重新读取端口。 对于写端口 res,数据必须保存到一个临时变量中,并且只能在红色显示的周期内写入端口。

所以要对设计进行拓展实现图中的数组的赋值操作。main函数修改成下面:

#include "matrixmul.h"
void matrixmul(
      mat_a_t a[MAT_A_ROWS][MAT_A_COLS],
      mat_b_t b[MAT_B_ROWS][MAT_B_COLS],
      result_t res[MAT_A_ROWS][MAT_B_COLS])
{
  mat_a_t a_row[MAT_A_ROWS];
  mat_b_t b_copy[MAT_B_ROWS][MAT_B_COLS];
  int tmp = 0;
  // Iterate over the rowa of the A matrix
  Row: for(int i = 0; i < MAT_A_ROWS; i++) {
    // Iterate over the columns of the B matrix
    Col: for(int j = 0; j < MAT_B_COLS; j++) {
      // Do the inner product of a row of A and col of B
      tmp=0;
      // Cache each row (so it's only read once per function)
      if (j == 0)
        Cache_Row: for(int k = 0; k < MAT_A_ROWS; k++)
          a_row[k] = a[i][k];
       // Cache all cols (so they are only read once per function)
     if (i == 0)
            Cache_Col: for(int k = 0; k < MAT_B_ROWS; k++)
               b_copy[k][j] = b[k][j];
      Product: for(int k = 0; k < MAT_B_ROWS; k++) {
        tmp += a_row[k] * b_copy[k][j];
      }
      res[i][j] = tmp;
    }
  }
}

指令修改成下图:

image.png

此时进行C综合可以完成综合,对比之前设计,此时的延迟进一步被优化,而资源仅仅在FF和LUT进行少量的增加。

image.png

references


  1. UG871


目录
相关文章
|
存储 人工智能 监控
HLS实践 - 06 - 优化设计(一)
HLS实践 - 06 - 优化设计
227 0
HLS实践 - 06 - 优化设计(一)
HLS实践 - 03 - 接口优化设计(一)
HLS实践 - 03 - 接口优化设计
266 0
HLS实践 - 03 - 接口优化设计(一)
HLS实践 - 03 - 接口优化设计(二)
HLS实践 - 03 - 接口优化设计
304 0
HLS实践 - 03 - 接口优化设计(二)
HLS开发学习-14- Vivado HLS 函数层面的优化
HLS开发学习-14- Vivado HLS 函数层面的优化
242 0
HLS开发学习-14- Vivado HLS 函数层面的优化
|
存储 测试技术 文件存储
HLS开发学习-09- 描述高效的C测试平台
HLS开发学习-09- 描述高效的C测试平台
685 0
HLS开发学习-09- 描述高效的C测试平台
|
存储
HLS开发学习-10- 接口综合
HLS开发学习-10- 接口综合
424 0
HLS开发学习-10- 接口综合
|
异构计算
HLS开发学习-13- 数组优化
HLS开发学习-13- 数组优化
346 0
HLS开发学习-13- 数组优化
|
编译器 异构计算 索引
HLS设计方法论 - 结构优化策略
HLS设计方法论 - 结构优化策略
173 0
HLS设计方法论 - 结构优化策略
|
存储
HLS实践 - 02 - 简单优化FIR设计
HLS实践 - 02 - 简单优化FIR设计
175 0
HLS实践 - 02 - 简单优化FIR设计
|
算法 Serverless 调度
HLS开发学习-02-HLS工作机制
HLS开发学习-02-HLS工作机制
311 0
HLS开发学习-02-HLS工作机制