次のコード例では、double
および struct
を使用して共用体を作成しています。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 デザインでは、生のビットを 1 つのデータ型から別のデータ型に変換するために共用体が使用されることがよくあります。通常、この生ビットの変換は、最上位ポート インターフェイスで浮動小数点値を使用する場合に必要です。次にその例を示します。
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++ データ型では問題なく、変更すれば double 型でも問題ありません。half 型はクラスであり、共用体では使用できないので、typedef
および int
を short
に変更することはできません。その代わりに、次のコードを使用できます。
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 ヘッダー ファイルを使用してください。