最优化逻辑表达式 - 2022.1 Chinese

Vitis 高层次综合用户指南 (UG1399)

Document ID
UG1399
Release Date
2022-06-07
Version
2022.1 简体中文

在综合期间会执行多次最优化(例如,强度折减和位宽最小化)。在自动最优化列表中也包括表达式平衡。

表达式平衡会重新排列运算符以构造平衡的树结构并降低时延。

  • 对于整数运算,默认情况下表达式平衡处于开启状态,但可使用 EXPRESSION_BALANCE 编译指示或指令将其禁用。
  • 对于浮点运算,默认情况下表达式平衡处于关闭状态,但可使用 config_compile -unsafe_math_optimizations 来启用,如下所述。

对于使用如下示例所示或者由循环展开而产生的 +=*= 之类的赋值运算符的高度循序代码:

data_t foo_top (data_t a, data_t b, data_t c, data_t d)
{
 data_t sum;

 sum = 0;
 sum += a;
 sum += b;
 sum += c;
 sum += d;
 return sum;

}

如果不使用表达式平衡并且假定每个加法都需要 1 个时钟周期,那么完整计算 sum 需要 4 个时钟周期,如下图所示。

图 1. 加法树

但加法 a+bc+d 可并行执行以缩减时延。经过平衡后,计算可在 2 个时钟周期内完成,如下图所示。表达式平衡禁止共享,导致面积增加。

图 2. 平衡后的加法树

对于整数,您可使用 EXPRESSION_BALANCE 最优化指令配合 off 选项来禁用表达式平衡。默认情况下,Vitis HLS 对于 float 类型或 double 类型的运算不执行 EXPRESSION_BALANCE 最优化。对 floatdouble 类型进行综合时,Vitis HLS 会保留 C/C++ 语言代码中执行的运算顺序,以确保结果与 C/C++ 语言仿真相同。例如,在以下代码示例中,所有变量类型均为 floatdoubleO1O2 即使看似执行相同的基本操作,其值也并不同。

A=B*C; A=B*F;
D=E*F; D=E*C;
O1=A*D O2=A*D;

此行为是 C/C++ 语言标准中执行 floatdouble 类型的运算时饱和和舍入所导致的结果。因此,存在类型为 floatdouble 的函数时,Vitis HLS 始终保留运算顺序不变,并且默认不执行表达式平衡。

您可为特定运算启用表达式平衡,或者也可对 float 类型和 double 类型启用表达式平衡,只需按如下所示方式使用 config_compile -unsafe_math_optimizations 命令即可:

  1. Vitis HLS IDE 中,选择Solution > Solution Settings(解决方案 > 解决方案设置)。
  2. 在“Solution Settings”(解决方案设置)对话框中,单击General(常规)类别,然后选择config_compile,并启用unsafe_math_optimizations

启用此设置后,Vitis HLS 即可更改运算顺序,以生成更优化的设计。但 C/RTL 协同仿真的结果可能与 C/C++ 语言仿真不同。

unsafe_math_optimizations 功能还支持 no_signed_zeros 最优化。no_signed_zeros 最优化可确保以下表达式配合 float 类型和 double 类型使用时结果完全相同:

x - 0.0 = x; 
x + 0.0 = x; 
0.0 - x = -x; 
x - x = 0.0; 
x*0.0 = 0.0;

如果不使用 no_signed_zeros 最优化,由于舍入,以上表达式结果将不同。通过在 config_compile 命令中仅选中该选项,即可选择在不使用表达式平衡的情况下执行此最优化。

提示: 使用 unsafe_math_optimizationsno_signed_zero 最优化时,RTL 实现结果将不同于 C/C++ 语言仿真。测试激励文件应可忽略结果中的轻微差异:检查范围,不执行精确比对。