ポインター - 2023.2 日本語

Vitis 高位合成ユーザー ガイド (UG1399)

Document ID
UG1399
Release Date
2023-12-18
Version
2023.2 日本語

ポインターは C/C++ コードで広範囲に使用され、合成でもサポートされていますが、コード内でのポインターの使用は避けることをお勧めします。これは、次の状況でポインターを使用する場合に特に当てはまります。

  • ポインターが同じ関数内で複数回アクセス (読み出しまたは書き込み) される場合。
  • ポインター配列を使用する場合、各ポインターが別のポインターではなく、スカラーまたはスカラー配列を指定する必要あり。
  • ポインターの型変換は標準 C/C++ 型間の変換の場合にのみサポートあり。
注記: ポインター ツー ポイントはサポートされません。

次のコード例に、複数のオブジェクトをポイントするポインターの合成サポートを示します。

#include "pointer_multi.h"

dout_t pointer_multi (sel_t sel, din_t pos) {
 static const dout_t a[8] = {1, 2, 3, 4, 5, 6, 7, 8};
 static const dout_t b[8] = {8, 7, 6, 5, 4, 3, 2, 1};

 dout_t* ptr;
 if (sel) 
 ptr = a; 
 else 
 ptr = b;

 return ptr[pos];
} 

Vitis HLS のポインター トゥ ポインターは合成ではサポートされますが、最上位インターフェイスでは (最上位関数への引数としては) サポートされません。ポインター トゥ ポインターを複数の関数で使用する場合、Vitis HLS でポインター トゥ ポインターを使用する関数すべてがインライン展開されます。複数の関数をインライン展開すると、実行時間が長くなります。

#include "pointer_double.h"

data_t sub(data_t ptr[10], data_t size, data_t**flagPtr)
{
 data_t x, i;

 x = 0;
 // Sum x if AND of local index and pointer to pointer index is true
 for(i=0; i<size; ++i)
   if (**flagPtr & i)
        x += *(ptr+i);
 return x;
}

data_t pointer_double(data_t pos, data_t x, data_t* flag)
{
 data_t array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
 data_t* ptrFlag;
 data_t i;

 ptrFlag = flag;

 // Write x into index position pos
 if (pos >=0 & pos < 10) 
 *(array+pos) = x;

 // Pass same index (as pos) as pointer to another function
 return sub(array, 10, &ptrFlag);
}

ポインターの配列も合成できます。次のコード例では、ポインターの配列がグローバル配列の 2 次元の開始位置を格納するために使用されています。ポインターの配列内のポインターは、スカラーまたはスカラーの配列のみを指定でき、ほかのポインターを指定することはできません。

#include "pointer_array.h"

data_t A[N][10];

data_t pointer_array(data_t B[N*10]) {
 data_t i,j;
 data_t sum1;

 // Array of pointers
 data_t* PtrA[N];

 // Store global array locations in temp pointer array
 for (i=0; i<N; ++i) 
    PtrA[i] = &(A[i][0]);

 // Copy input array using pointers
 for(i=0; i<N; ++i) 
    for(j=0; j<10; ++j) 
       *(PtrA[i]+j) = B[i*10 + j];

  // Sum input array
 sum1 = 0;
 for(i=0; i<N; ++i)
    for(j=0; j<10; ++j) 
       sum1 += *(PtrA[i] + j);

 return sum1;
}

ポインターの型変換は、ネイティブ C/C++ 型が使用される場合に合成でサポートされます。次のコード例では、int 型が char 型に変換されています。

#define N 1024

typedef int data_t;
typedef char dint_t;

data_t pointer_cast_native (data_t index, data_t A[N]) {
 dint_t* ptr;
 data_t i =0, result = 0;
 ptr = (dint_t*)(&A[index]);

 // Sum from the indexed value as a different type
 for (i = 0; i < 4*(N/10); ++i) {
   result += *ptr;
   ptr+=1;
 }
 return result;
} 

Vitis HLS では、一般的なデータ型間のポインター型変換はサポートされません。たとえば、符号付きの値の struct 複合型が作成されると、ポインターを型変換して符号なしの値を代入することはできません。

struct { 
 short first;  
 short second;  
} pair;

// Not supported for synthesis
*(unsigned*)(&pair) = -1U;

このような場合、値はネイティブ型を使用して代入する必要があります。

struct { 
 short first;  
 short second;  
} pair;

// Assigned value
pair.first = -1U; 
pair.second = -1U;