在以下代码示例中,已创建含 double
和 struct
的联合体 (union)。不同于 C/C++ 编译,综合并不保证针对 union
中的所有字段使用相同存储器(对于综合,则不保证使用相同寄存器)。Vitis HLS 通过执行最优化来提供最优硬件。
#include "types_union.h"
dout_t types_union(din_t N, dinfp_t F)
{
union {
struct {int a; int b; } intval;
double fpval;
} intfp;
unsigned long long one, exp;
// Set a floating-point value in union intfp
intfp.fpval = F;
// Slice out lower bits and add to shifted input
one = intfp.intval.a;
exp = (N & 0x7FF);
return ((exp << 52) + one) & (0x7fffffffffffffffLL);
}
Vitis HLS 不支持:
- 顶层函数接口上的联合体。
- 重新解读指针以供综合。因此,联合体不能保存不同类型的指针,也不能保存指向不同类型的阵列的指针。
- 通过其他变量访问联合体。同样使用上述示例中的联合体,不支持:
for (int i = 0; i < 6; ++i) if (i<3) A[i] = intfp.intval.a + B[i]; else A[i] = intfp.intval.b + B[i]; }
- 但可将其显式重编码为:
A[0] = intfp.intval.a + B[0]; A[1] = intfp.intval.a + B[1]; A[2] = intfp.intval.a + B[2]; A[3] = intfp.intval.b + B[3]; A[4] = intfp.intval.b + B[4]; A[5] = intfp.intval.b + B[5];
对联合体进行综合不支持原生 C/C++ 类型与用户定义的类型之间进行类型强制转换。
在 Vitis HLS 设计中,联合体常用于转换原始位元的数据类型。通常在顶层端口接口处使用浮点值时,需使用此原始位元转换。请参阅以下示例:
typedef float T;
unsigned int value; // the "input"€ of the conversion
T myhalfvalue; // the "output" of the conversion
union
{
unsigned int as_uint32;
T as_floatingpoint;
} my_converter;
my_converter.as_uint32 = value;
myhalfvalue = my_converter. as_floatingpoint;
这种类型的代码适用于 C/C++ 语言的浮点 (float) 数据类型,通过修改还可用于双精度 (double) 数据类型。将 typedef
和 int
更改为 short
对于 half 数据类型无效,但由于 half 属于类,因此在联合体中无法使用。可改用以下代码:
typedef half T;
short value;
T myhalfvalue = static_cast<T>(value);
同样,相反方式的转换使用的是 value=static_cast<ap_uint<16> >(myhalfvalue)
或 static_cast< unsigned short >(myhalfvalue)
。
ap_fixed<16,4> afix = 1.5;
ap_fixed<20,6> bfix = 1.25;
half ahlf = afix.to_half();
half bhlf = bfix.to_half();
另一种方法是使用帮助程序类 fp_struct<half>
来通过 data()
或 to_int()
方法进行转换。使用 hls/utils/x_hls_utils.h 头文件。